help@rskworld.in +91 93305 39277
RSK World
  • Home
  • Development
    • Web Development
    • Mobile Apps
    • Software
    • Games
    • Project
  • Technologies
    • Data Science
    • AI Development
    • Cloud Development
    • Blockchain
    • Cyber Security
    • Dev Tools
    • Testing Tools
  • Blog
  • About
  • Contact

Theme Settings

Color Scheme
Display Options
Font Size
100%
Back to Project
RSK World
travel-assistant-bot
/
.venv
/
Lib
/
site-packages
/
pip
/
_vendor
/
rich
RSK World
travel-assistant-bot
Travel Assistant Bot - Python + Flask + OpenAI API + Travel Bot + Flight Search + Hotel Booking + Weather
rich
  • __pycache__
  • __init__.py5.9 KB
  • __main__.py8.3 KB
  • _cell_widths.py10 KB
  • _emoji_codes.py136.9 KB
  • _emoji_replace.py1 KB
  • _export_format.py2.1 KB
  • _extension.py265 B
  • _fileno.py799 B
  • _inspect.py9.5 KB
  • _log_render.py3.1 KB
  • _loop.py1.2 KB
  • _null_file.py1.4 KB
  • _palettes.py6.9 KB
  • _pick.py423 B
  • _ratio.py5.3 KB
  • _spinners.py19.5 KB
  • _stack.py351 B
  • _timer.py417 B
  • _win32_console.py22.3 KB
  • _windows.py1.9 KB
  • _windows_renderer.py2.7 KB
  • _wrap.py3.3 KB
  • abc.py890 B
  • align.py10.1 KB
  • ansi.py6.7 KB
  • bar.py3.2 KB
  • box.py10.6 KB
  • cells.py4.7 KB
  • color.py17.8 KB
  • color_triplet.py1 KB
  • columns.py7 KB
  • console.py96.8 KB
  • constrain.py1.3 KB
  • containers.py5.4 KB
  • control.py6.5 KB
  • default_styles.py7.9 KB
  • diagnose.py972 B
  • emoji.py2.4 KB
  • errors.py642 B
  • file_proxy.py1.6 KB
  • filesize.py2.4 KB
  • highlighter.py9.4 KB
  • json.py4.9 KB
  • jupyter.py3.2 KB
  • layout.py13.7 KB
  • live.py13.9 KB
  • live_render.py3.6 KB
  • logging.py11.6 KB
  • markup.py8.3 KB
  • measure.py5.2 KB
  • padding.py4.9 KB
  • pager.py828 B
  • palette.py3.3 KB
  • panel.py10.5 KB
  • pretty.py35 KB
  • progress.py58.3 KB
  • progress_bar.py8 KB
  • prompt.py11 KB
  • protocol.py1.4 KB
  • py.typed0 B
  • region.py166 B
  • repr.py4.3 KB
  • rule.py4.5 KB
  • scope.py2.8 KB
  • screen.py1.6 KB
  • segment.py23.7 KB
  • spinner.py4.2 KB
  • status.py4.3 KB
  • style.py26.4 KB
  • styled.py1.2 KB
  • syntax.py34.6 KB
  • table.py38.8 KB
  • terminal_theme.py3.3 KB
  • text.py46.2 KB
  • theme.py3.7 KB
  • themes.py102 B
  • traceback.py28.9 KB
  • tree.py9 KB
theme.pycerts.py__init__.py_win32_console.pyscreen.pyreq_uninstall.pyadapters.py_emoji_replace.pystatus.pyfilesize.py__init__.pyuts46data.pywheel.pylive.py_wrap.pystructs.py
.venv/Lib/site-packages/pip/_vendor/rich/theme.py
Raw Download
Find: Go to:
import configparser
from typing import Dict, List, IO, Mapping, Optional

from .default_styles import DEFAULT_STYLES
from .style import Style, StyleType


class Theme:
    """A container for style information, used by :class:`~rich.console.Console`.

    Args:
        styles (Dict[str, Style], optional): A mapping of style names on to styles. Defaults to None for a theme with no styles.
        inherit (bool, optional): Inherit default styles. Defaults to True.
    """

    styles: Dict[str, Style]

    def __init__(
        self, styles: Optional[Mapping[str, StyleType]] = None, inherit: bool = True
    ):
        self.styles = DEFAULT_STYLES.copy() if inherit else {}
        if styles is not None:
            self.styles.update(
                {
                    name: style if isinstance(style, Style) else Style.parse(style)
                    for name, style in styles.items()
                }
            )

    @property
    def config(self) -> str:
        """Get contents of a config file for this theme."""
        config = "[styles]\n" + "\n".join(
            f"{name} = {style}" for name, style in sorted(self.styles.items())
        )
        return config

    @classmethod
    def from_file(
        cls, config_file: IO[str], source: Optional[str] = None, inherit: bool = True
    ) -> "Theme":
        """Load a theme from a text mode file.

        Args:
            config_file (IO[str]): An open conf file.
            source (str, optional): The filename of the open file. Defaults to None.
            inherit (bool, optional): Inherit default styles. Defaults to True.

        Returns:
            Theme: A New theme instance.
        """
        config = configparser.ConfigParser()
        config.read_file(config_file, source=source)
        styles = {name: Style.parse(value) for name, value in config.items("styles")}
        theme = Theme(styles, inherit=inherit)
        return theme

    @classmethod
    def read(
        cls, path: str, inherit: bool = True, encoding: Optional[str] = None
    ) -> "Theme":
        """Read a theme from a path.

        Args:
            path (str): Path to a config file readable by Python configparser module.
            inherit (bool, optional): Inherit default styles. Defaults to True.
            encoding (str, optional): Encoding of the config file. Defaults to None.

        Returns:
            Theme: A new theme instance.
        """
        with open(path, "rt", encoding=encoding) as config_file:
            return cls.from_file(config_file, source=path, inherit=inherit)


class ThemeStackError(Exception):
    """Base exception for errors related to the theme stack."""


class ThemeStack:
    """A stack of themes.

    Args:
        theme (Theme): A theme instance
    """

    def __init__(self, theme: Theme) -> None:
        self._entries: List[Dict[str, Style]] = [theme.styles]
        self.get = self._entries[-1].get

    def push_theme(self, theme: Theme, inherit: bool = True) -> None:
        """Push a theme on the top of the stack.

        Args:
            theme (Theme): A Theme instance.
            inherit (boolean, optional): Inherit styles from current top of stack.
        """
        styles: Dict[str, Style]
        styles = (
            {**self._entries[-1], **theme.styles} if inherit else theme.styles.copy()
        )
        self._entries.append(styles)
        self.get = self._entries[-1].get

    def pop_theme(self) -> None:
        """Pop (and discard) the top-most theme."""
        if len(self._entries) == 1:
            raise ThemeStackError("Unable to pop base theme")
        self._entries.pop()
        self.get = self._entries[-1].get


if __name__ == "__main__":  # pragma: no cover
    theme = Theme()
    print(theme.config)
116 lines•3.7 KB
python
.venv/Lib/site-packages/pip/_vendor/requests/certs.py
Raw Download
Find: Go to:
#!/usr/bin/env python

"""
requests.certs
~~~~~~~~~~~~~~

This module returns the preferred default CA certificate bundle. There is
only one — the one from the certifi package.

If you are packaging Requests, e.g., for a Linux distribution or a managed
environment, you can change the definition of where() to return a separately
packaged CA bundle.
"""

import os

if "_PIP_STANDALONE_CERT" not in os.environ:
    from pip._vendor.certifi import where
else:
    def where():
        return os.environ["_PIP_STANDALONE_CERT"]

if __name__ == "__main__":
    print(where())
25 lines•575 B
python
.venv/Lib/site-packages/pip/_vendor/tomli/__init__.py
Raw Download
Find: Go to:
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: 2021 Taneli Hukkinen
# Licensed to PSF under a Contributor Agreement.

__all__ = ("loads", "load", "TOMLDecodeError")
__version__ = "2.0.1"  # DO NOT EDIT THIS LINE MANUALLY. LET bump2version UTILITY DO IT

from ._parser import TOMLDecodeError, load, loads

# Pretend this exception was created here.
TOMLDecodeError.__module__ = __name__
12 lines•396 B
python
.venv/Lib/site-packages/pip/_vendor/rich/_win32_console.py
Raw Download
Find: Go to:
"""Light wrapper around the Win32 Console API - this module should only be imported on Windows

The API that this module wraps is documented at https://docs.microsoft.com/en-us/windows/console/console-functions
"""
import ctypes
import sys
from typing import Any

windll: Any = None
if sys.platform == "win32":
    windll = ctypes.LibraryLoader(ctypes.WinDLL)
else:
    raise ImportError(f"{__name__} can only be imported on Windows")

import time
from ctypes import Structure, byref, wintypes
from typing import IO, NamedTuple, Type, cast

from pip._vendor.rich.color import ColorSystem
from pip._vendor.rich.style import Style

STDOUT = -11
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4

COORD = wintypes._COORD


class LegacyWindowsError(Exception):
    pass


class WindowsCoordinates(NamedTuple):
    """Coordinates in the Windows Console API are (y, x), not (x, y).
    This class is intended to prevent that confusion.
    Rows and columns are indexed from 0.
    This class can be used in place of wintypes._COORD in arguments and argtypes.
    """

    row: int
    col: int

    @classmethod
    def from_param(cls, value: "WindowsCoordinates") -> COORD:
        """Converts a WindowsCoordinates into a wintypes _COORD structure.
        This classmethod is internally called by ctypes to perform the conversion.

        Args:
            value (WindowsCoordinates): The input coordinates to convert.

        Returns:
            wintypes._COORD: The converted coordinates struct.
        """
        return COORD(value.col, value.row)


class CONSOLE_SCREEN_BUFFER_INFO(Structure):
    _fields_ = [
        ("dwSize", COORD),
        ("dwCursorPosition", COORD),
        ("wAttributes", wintypes.WORD),
        ("srWindow", wintypes.SMALL_RECT),
        ("dwMaximumWindowSize", COORD),
    ]


class CONSOLE_CURSOR_INFO(ctypes.Structure):
    _fields_ = [("dwSize", wintypes.DWORD), ("bVisible", wintypes.BOOL)]


_GetStdHandle = windll.kernel32.GetStdHandle
_GetStdHandle.argtypes = [
    wintypes.DWORD,
]
_GetStdHandle.restype = wintypes.HANDLE


def GetStdHandle(handle: int = STDOUT) -> wintypes.HANDLE:
    """Retrieves a handle to the specified standard device (standard input, standard output, or standard error).

    Args:
        handle (int): Integer identifier for the handle. Defaults to -11 (stdout).

    Returns:
        wintypes.HANDLE: The handle
    """
    return cast(wintypes.HANDLE, _GetStdHandle(handle))


_GetConsoleMode = windll.kernel32.GetConsoleMode
_GetConsoleMode.argtypes = [wintypes.HANDLE, wintypes.LPDWORD]
_GetConsoleMode.restype = wintypes.BOOL


def GetConsoleMode(std_handle: wintypes.HANDLE) -> int:
    """Retrieves the current input mode of a console's input buffer
    or the current output mode of a console screen buffer.

    Args:
        std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer.

    Raises:
        LegacyWindowsError: If any error occurs while calling the Windows console API.

    Returns:
        int: Value representing the current console mode as documented at
            https://docs.microsoft.com/en-us/windows/console/getconsolemode#parameters
    """

    console_mode = wintypes.DWORD()
    success = bool(_GetConsoleMode(std_handle, console_mode))
    if not success:
        raise LegacyWindowsError("Unable to get legacy Windows Console Mode")
    return console_mode.value


_FillConsoleOutputCharacterW = windll.kernel32.FillConsoleOutputCharacterW
_FillConsoleOutputCharacterW.argtypes = [
    wintypes.HANDLE,
    ctypes.c_char,
    wintypes.DWORD,
    cast(Type[COORD], WindowsCoordinates),
    ctypes.POINTER(wintypes.DWORD),
]
_FillConsoleOutputCharacterW.restype = wintypes.BOOL


def FillConsoleOutputCharacter(
    std_handle: wintypes.HANDLE,
    char: str,
    length: int,
    start: WindowsCoordinates,
) -> int:
    """Writes a character to the console screen buffer a specified number of times, beginning at the specified coordinates.

    Args:
        std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer.
        char (str): The character to write. Must be a string of length 1.
        length (int): The number of times to write the character.
        start (WindowsCoordinates): The coordinates to start writing at.

    Returns:
        int: The number of characters written.
    """
    character = ctypes.c_char(char.encode())
    num_characters = wintypes.DWORD(length)
    num_written = wintypes.DWORD(0)
    _FillConsoleOutputCharacterW(
        std_handle,
        character,
        num_characters,
        start,
        byref(num_written),
    )
    return num_written.value


_FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute
_FillConsoleOutputAttribute.argtypes = [
    wintypes.HANDLE,
    wintypes.WORD,
    wintypes.DWORD,
    cast(Type[COORD], WindowsCoordinates),
    ctypes.POINTER(wintypes.DWORD),
]
_FillConsoleOutputAttribute.restype = wintypes.BOOL


def FillConsoleOutputAttribute(
    std_handle: wintypes.HANDLE,
    attributes: int,
    length: int,
    start: WindowsCoordinates,
) -> int:
    """Sets the character attributes for a specified number of character cells,
    beginning at the specified coordinates in a screen buffer.

    Args:
        std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer.
        attributes (int): Integer value representing the foreground and background colours of the cells.
        length (int): The number of cells to set the output attribute of.
        start (WindowsCoordinates): The coordinates of the first cell whose attributes are to be set.

    Returns:
        int: The number of cells whose attributes were actually set.
    """
    num_cells = wintypes.DWORD(length)
    style_attrs = wintypes.WORD(attributes)
    num_written = wintypes.DWORD(0)
    _FillConsoleOutputAttribute(
        std_handle, style_attrs, num_cells, start, byref(num_written)
    )
    return num_written.value


_SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute
_SetConsoleTextAttribute.argtypes = [
    wintypes.HANDLE,
    wintypes.WORD,
]
_SetConsoleTextAttribute.restype = wintypes.BOOL


def SetConsoleTextAttribute(
    std_handle: wintypes.HANDLE, attributes: wintypes.WORD
) -> bool:
    """Set the colour attributes for all text written after this function is called.

    Args:
        std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer.
        attributes (int): Integer value representing the foreground and background colours.


    Returns:
        bool: True if the attribute was set successfully, otherwise False.
    """
    return bool(_SetConsoleTextAttribute(std_handle, attributes))


_GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo
_GetConsoleScreenBufferInfo.argtypes = [
    wintypes.HANDLE,
    ctypes.POINTER(CONSOLE_SCREEN_BUFFER_INFO),
]
_GetConsoleScreenBufferInfo.restype = wintypes.BOOL


def GetConsoleScreenBufferInfo(
    std_handle: wintypes.HANDLE,
) -> CONSOLE_SCREEN_BUFFER_INFO:
    """Retrieves information about the specified console screen buffer.

    Args:
        std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer.

    Returns:
        CONSOLE_SCREEN_BUFFER_INFO: A CONSOLE_SCREEN_BUFFER_INFO ctype struct contain information about
            screen size, cursor position, colour attributes, and more."""
    console_screen_buffer_info = CONSOLE_SCREEN_BUFFER_INFO()
    _GetConsoleScreenBufferInfo(std_handle, byref(console_screen_buffer_info))
    return console_screen_buffer_info


_SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition
_SetConsoleCursorPosition.argtypes = [
    wintypes.HANDLE,
    cast(Type[COORD], WindowsCoordinates),
]
_SetConsoleCursorPosition.restype = wintypes.BOOL


def SetConsoleCursorPosition(
    std_handle: wintypes.HANDLE, coords: WindowsCoordinates
) -> bool:
    """Set the position of the cursor in the console screen

    Args:
        std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer.
        coords (WindowsCoordinates): The coordinates to move the cursor to.

    Returns:
        bool: True if the function succeeds, otherwise False.
    """
    return bool(_SetConsoleCursorPosition(std_handle, coords))


_GetConsoleCursorInfo = windll.kernel32.GetConsoleCursorInfo
_GetConsoleCursorInfo.argtypes = [
    wintypes.HANDLE,
    ctypes.POINTER(CONSOLE_CURSOR_INFO),
]
_GetConsoleCursorInfo.restype = wintypes.BOOL


def GetConsoleCursorInfo(
    std_handle: wintypes.HANDLE, cursor_info: CONSOLE_CURSOR_INFO
) -> bool:
    """Get the cursor info - used to get cursor visibility and width

    Args:
        std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer.
        cursor_info (CONSOLE_CURSOR_INFO): CONSOLE_CURSOR_INFO ctype struct that receives information
            about the console's cursor.

    Returns:
          bool: True if the function succeeds, otherwise False.
    """
    return bool(_GetConsoleCursorInfo(std_handle, byref(cursor_info)))


_SetConsoleCursorInfo = windll.kernel32.SetConsoleCursorInfo
_SetConsoleCursorInfo.argtypes = [
    wintypes.HANDLE,
    ctypes.POINTER(CONSOLE_CURSOR_INFO),
]
_SetConsoleCursorInfo.restype = wintypes.BOOL


def SetConsoleCursorInfo(
    std_handle: wintypes.HANDLE, cursor_info: CONSOLE_CURSOR_INFO
) -> bool:
    """Set the cursor info - used for adjusting cursor visibility and width

    Args:
        std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer.
        cursor_info (CONSOLE_CURSOR_INFO): CONSOLE_CURSOR_INFO ctype struct containing the new cursor info.

    Returns:
          bool: True if the function succeeds, otherwise False.
    """
    return bool(_SetConsoleCursorInfo(std_handle, byref(cursor_info)))


_SetConsoleTitle = windll.kernel32.SetConsoleTitleW
_SetConsoleTitle.argtypes = [wintypes.LPCWSTR]
_SetConsoleTitle.restype = wintypes.BOOL


def SetConsoleTitle(title: str) -> bool:
    """Sets the title of the current console window

    Args:
        title (str): The new title of the console window.

    Returns:
        bool: True if the function succeeds, otherwise False.
    """
    return bool(_SetConsoleTitle(title))


class LegacyWindowsTerm:
    """This class allows interaction with the legacy Windows Console API. It should only be used in the context
    of environments where virtual terminal processing is not available. However, if it is used in a Windows environment,
    the entire API should work.

    Args:
        file (IO[str]): The file which the Windows Console API HANDLE is retrieved from, defaults to sys.stdout.
    """

    BRIGHT_BIT = 8

    # Indices are ANSI color numbers, values are the corresponding Windows Console API color numbers
    ANSI_TO_WINDOWS = [
        0,  # black                      The Windows colours are defined in wincon.h as follows:
        4,  # red                         define FOREGROUND_BLUE            0x0001 -- 0000 0001
        2,  # green                       define FOREGROUND_GREEN           0x0002 -- 0000 0010
        6,  # yellow                      define FOREGROUND_RED             0x0004 -- 0000 0100
        1,  # blue                        define FOREGROUND_INTENSITY       0x0008 -- 0000 1000
        5,  # magenta                     define BACKGROUND_BLUE            0x0010 -- 0001 0000
        3,  # cyan                        define BACKGROUND_GREEN           0x0020 -- 0010 0000
        7,  # white                       define BACKGROUND_RED             0x0040 -- 0100 0000
        8,  # bright black (grey)         define BACKGROUND_INTENSITY       0x0080 -- 1000 0000
        12,  # bright red
        10,  # bright green
        14,  # bright yellow
        9,  # bright blue
        13,  # bright magenta
        11,  # bright cyan
        15,  # bright white
    ]

    def __init__(self, file: "IO[str]") -> None:
        handle = GetStdHandle(STDOUT)
        self._handle = handle
        default_text = GetConsoleScreenBufferInfo(handle).wAttributes
        self._default_text = default_text

        self._default_fore = default_text & 7
        self._default_back = (default_text >> 4) & 7
        self._default_attrs = self._default_fore | (self._default_back << 4)

        self._file = file
        self.write = file.write
        self.flush = file.flush

    @property
    def cursor_position(self) -> WindowsCoordinates:
        """Returns the current position of the cursor (0-based)

        Returns:
            WindowsCoordinates: The current cursor position.
        """
        coord: COORD = GetConsoleScreenBufferInfo(self._handle).dwCursorPosition
        return WindowsCoordinates(row=cast(int, coord.Y), col=cast(int, coord.X))

    @property
    def screen_size(self) -> WindowsCoordinates:
        """Returns the current size of the console screen buffer, in character columns and rows

        Returns:
            WindowsCoordinates: The width and height of the screen as WindowsCoordinates.
        """
        screen_size: COORD = GetConsoleScreenBufferInfo(self._handle).dwSize
        return WindowsCoordinates(
            row=cast(int, screen_size.Y), col=cast(int, screen_size.X)
        )

    def write_text(self, text: str) -> None:
        """Write text directly to the terminal without any modification of styles

        Args:
            text (str): The text to write to the console
        """
        self.write(text)
        self.flush()

    def write_styled(self, text: str, style: Style) -> None:
        """Write styled text to the terminal.

        Args:
            text (str): The text to write
            style (Style): The style of the text
        """
        color = style.color
        bgcolor = style.bgcolor
        if style.reverse:
            color, bgcolor = bgcolor, color

        if color:
            fore = color.downgrade(ColorSystem.WINDOWS).number
            fore = fore if fore is not None else 7  # Default to ANSI 7: White
            if style.bold:
                fore = fore | self.BRIGHT_BIT
            if style.dim:
                fore = fore & ~self.BRIGHT_BIT
            fore = self.ANSI_TO_WINDOWS[fore]
        else:
            fore = self._default_fore

        if bgcolor:
            back = bgcolor.downgrade(ColorSystem.WINDOWS).number
            back = back if back is not None else 0  # Default to ANSI 0: Black
            back = self.ANSI_TO_WINDOWS[back]
        else:
            back = self._default_back

        assert fore is not None
        assert back is not None

        SetConsoleTextAttribute(
            self._handle, attributes=ctypes.c_ushort(fore | (back << 4))
        )
        self.write_text(text)
        SetConsoleTextAttribute(self._handle, attributes=self._default_text)

    def move_cursor_to(self, new_position: WindowsCoordinates) -> None:
        """Set the position of the cursor

        Args:
            new_position (WindowsCoordinates): The WindowsCoordinates representing the new position of the cursor.
        """
        if new_position.col < 0 or new_position.row < 0:
            return
        SetConsoleCursorPosition(self._handle, coords=new_position)

    def erase_line(self) -> None:
        """Erase all content on the line the cursor is currently located at"""
        screen_size = self.screen_size
        cursor_position = self.cursor_position
        cells_to_erase = screen_size.col
        start_coordinates = WindowsCoordinates(row=cursor_position.row, col=0)
        FillConsoleOutputCharacter(
            self._handle, " ", length=cells_to_erase, start=start_coordinates
        )
        FillConsoleOutputAttribute(
            self._handle,
            self._default_attrs,
            length=cells_to_erase,
            start=start_coordinates,
        )

    def erase_end_of_line(self) -> None:
        """Erase all content from the cursor position to the end of that line"""
        cursor_position = self.cursor_position
        cells_to_erase = self.screen_size.col - cursor_position.col
        FillConsoleOutputCharacter(
            self._handle, " ", length=cells_to_erase, start=cursor_position
        )
        FillConsoleOutputAttribute(
            self._handle,
            self._default_attrs,
            length=cells_to_erase,
            start=cursor_position,
        )

    def erase_start_of_line(self) -> None:
        """Erase all content from the cursor position to the start of that line"""
        row, col = self.cursor_position
        start = WindowsCoordinates(row, 0)
        FillConsoleOutputCharacter(self._handle, " ", length=col, start=start)
        FillConsoleOutputAttribute(
            self._handle, self._default_attrs, length=col, start=start
        )

    def move_cursor_up(self) -> None:
        """Move the cursor up a single cell"""
        cursor_position = self.cursor_position
        SetConsoleCursorPosition(
            self._handle,
            coords=WindowsCoordinates(
                row=cursor_position.row - 1, col=cursor_position.col
            ),
        )

    def move_cursor_down(self) -> None:
        """Move the cursor down a single cell"""
        cursor_position = self.cursor_position
        SetConsoleCursorPosition(
            self._handle,
            coords=WindowsCoordinates(
                row=cursor_position.row + 1,
                col=cursor_position.col,
            ),
        )

    def move_cursor_forward(self) -> None:
        """Move the cursor forward a single cell. Wrap to the next line if required."""
        row, col = self.cursor_position
        if col == self.screen_size.col - 1:
            row += 1
            col = 0
        else:
            col += 1
        SetConsoleCursorPosition(
            self._handle, coords=WindowsCoordinates(row=row, col=col)
        )

    def move_cursor_to_column(self, column: int) -> None:
        """Move cursor to the column specified by the zero-based column index, staying on the same row

        Args:
            column (int): The zero-based column index to move the cursor to.
        """
        row, _ = self.cursor_position
        SetConsoleCursorPosition(self._handle, coords=WindowsCoordinates(row, column))

    def move_cursor_backward(self) -> None:
        """Move the cursor backward a single cell. Wrap to the previous line if required."""
        row, col = self.cursor_position
        if col == 0:
            row -= 1
            col = self.screen_size.col - 1
        else:
            col -= 1
        SetConsoleCursorPosition(
            self._handle, coords=WindowsCoordinates(row=row, col=col)
        )

    def hide_cursor(self) -> None:
        """Hide the cursor"""
        current_cursor_size = self._get_cursor_size()
        invisible_cursor = CONSOLE_CURSOR_INFO(dwSize=current_cursor_size, bVisible=0)
        SetConsoleCursorInfo(self._handle, cursor_info=invisible_cursor)

    def show_cursor(self) -> None:
        """Show the cursor"""
        current_cursor_size = self._get_cursor_size()
        visible_cursor = CONSOLE_CURSOR_INFO(dwSize=current_cursor_size, bVisible=1)
        SetConsoleCursorInfo(self._handle, cursor_info=visible_cursor)

    def set_title(self, title: str) -> None:
        """Set the title of the terminal window

        Args:
            title (str): The new title of the console window
        """
        assert len(title) < 255, "Console title must be less than 255 characters"
        SetConsoleTitle(title)

    def _get_cursor_size(self) -> int:
        """Get the percentage of the character cell that is filled by the cursor"""
        cursor_info = CONSOLE_CURSOR_INFO()
        GetConsoleCursorInfo(self._handle, cursor_info=cursor_info)
        return int(cursor_info.dwSize)


if __name__ == "__main__":
    handle = GetStdHandle()

    from pip._vendor.rich.console import Console

    console = Console()

    term = LegacyWindowsTerm(sys.stdout)
    term.set_title("Win32 Console Examples")

    style = Style(color="black", bgcolor="red")

    heading = Style.parse("black on green")

    # Check colour output
    console.rule("Checking colour output")
    console.print("[on red]on red!")
    console.print("[blue]blue!")
    console.print("[yellow]yellow!")
    console.print("[bold yellow]bold yellow!")
    console.print("[bright_yellow]bright_yellow!")
    console.print("[dim bright_yellow]dim bright_yellow!")
    console.print("[italic cyan]italic cyan!")
    console.print("[bold white on blue]bold white on blue!")
    console.print("[reverse bold white on blue]reverse bold white on blue!")
    console.print("[bold black on cyan]bold black on cyan!")
    console.print("[black on green]black on green!")
    console.print("[blue on green]blue on green!")
    console.print("[white on black]white on black!")
    console.print("[black on white]black on white!")
    console.print("[#1BB152 on #DA812D]#1BB152 on #DA812D!")

    # Check cursor movement
    console.rule("Checking cursor movement")
    console.print()
    term.move_cursor_backward()
    term.move_cursor_backward()
    term.write_text("went back and wrapped to prev line")
    time.sleep(1)
    term.move_cursor_up()
    term.write_text("we go up")
    time.sleep(1)
    term.move_cursor_down()
    term.write_text("and down")
    time.sleep(1)
    term.move_cursor_up()
    term.move_cursor_backward()
    term.move_cursor_backward()
    term.write_text("we went up and back 2")
    time.sleep(1)
    term.move_cursor_down()
    term.move_cursor_backward()
    term.move_cursor_backward()
    term.write_text("we went down and back 2")
    time.sleep(1)

    # Check erasing of lines
    term.hide_cursor()
    console.print()
    console.rule("Checking line erasing")
    console.print("\n...Deleting to the start of the line...")
    term.write_text("The red arrow shows the cursor location, and direction of erase")
    time.sleep(1)
    term.move_cursor_to_column(16)
    term.write_styled("<", Style.parse("black on red"))
    term.move_cursor_backward()
    time.sleep(1)
    term.erase_start_of_line()
    time.sleep(1)

    console.print("\n\n...And to the end of the line...")
    term.write_text("The red arrow shows the cursor location, and direction of erase")
    time.sleep(1)

    term.move_cursor_to_column(16)
    term.write_styled(">", Style.parse("black on red"))
    time.sleep(1)
    term.erase_end_of_line()
    time.sleep(1)

    console.print("\n\n...Now the whole line will be erased...")
    term.write_styled("I'm going to disappear!", style=Style.parse("black on cyan"))
    time.sleep(1)
    term.erase_line()

    term.show_cursor()
    print("\n")
663 lines•22.3 KB
python
.venv/Lib/site-packages/pip/_vendor/rich/screen.py
Raw Download
Find: Go to:
from typing import Optional, TYPE_CHECKING

from .segment import Segment
from .style import StyleType
from ._loop import loop_last


if TYPE_CHECKING:
    from .console import (
        Console,
        ConsoleOptions,
        RenderResult,
        RenderableType,
        Group,
    )


class Screen:
    """A renderable that fills the terminal screen and crops excess.

    Args:
        renderable (RenderableType): Child renderable.
        style (StyleType, optional): Optional background style. Defaults to None.
    """

    renderable: "RenderableType"

    def __init__(
        self,
        *renderables: "RenderableType",
        style: Optional[StyleType] = None,
        application_mode: bool = False,
    ) -> None:
        from pip._vendor.rich.console import Group

        self.renderable = Group(*renderables)
        self.style = style
        self.application_mode = application_mode

    def __rich_console__(
        self, console: "Console", options: "ConsoleOptions"
    ) -> "RenderResult":
        width, height = options.size
        style = console.get_style(self.style) if self.style else None
        render_options = options.update(width=width, height=height)
        lines = console.render_lines(
            self.renderable or "", render_options, style=style, pad=True
        )
        lines = Segment.set_shape(lines, width, height, style=style)
        new_line = Segment("\n\r") if self.application_mode else Segment.line()
        for last, line in loop_last(lines):
            yield from line
            if not last:
                yield new_line
55 lines•1.6 KB
python
.venv/Lib/site-packages/pip/_internal/req/req_uninstall.py
Raw Download
Find: Go to:
import functools
import os
import sys
import sysconfig
from importlib.util import cache_from_source
from typing import Any, Callable, Dict, Generator, Iterable, List, Optional, Set, Tuple

from pip._internal.exceptions import LegacyDistutilsInstall, UninstallMissingRecord
from pip._internal.locations import get_bin_prefix, get_bin_user
from pip._internal.metadata import BaseDistribution
from pip._internal.utils.compat import WINDOWS
from pip._internal.utils.egg_link import egg_link_path_from_location
from pip._internal.utils.logging import getLogger, indent_log
from pip._internal.utils.misc import ask, normalize_path, renames, rmtree
from pip._internal.utils.temp_dir import AdjacentTempDirectory, TempDirectory
from pip._internal.utils.virtualenv import running_under_virtualenv

logger = getLogger(__name__)


def _script_names(
    bin_dir: str, script_name: str, is_gui: bool
) -> Generator[str, None, None]:
    """Create the fully qualified name of the files created by
    {console,gui}_scripts for the given ``dist``.
    Returns the list of file names
    """
    exe_name = os.path.join(bin_dir, script_name)
    yield exe_name
    if not WINDOWS:
        return
    yield f"{exe_name}.exe"
    yield f"{exe_name}.exe.manifest"
    if is_gui:
        yield f"{exe_name}-script.pyw"
    else:
        yield f"{exe_name}-script.py"


def _unique(
    fn: Callable[..., Generator[Any, None, None]]
) -> Callable[..., Generator[Any, None, None]]:
    @functools.wraps(fn)
    def unique(*args: Any, **kw: Any) -> Generator[Any, None, None]:
        seen: Set[Any] = set()
        for item in fn(*args, **kw):
            if item not in seen:
                seen.add(item)
                yield item

    return unique


@_unique
def uninstallation_paths(dist: BaseDistribution) -> Generator[str, None, None]:
    """
    Yield all the uninstallation paths for dist based on RECORD-without-.py[co]

    Yield paths to all the files in RECORD. For each .py file in RECORD, add
    the .pyc and .pyo in the same directory.

    UninstallPathSet.add() takes care of the __pycache__ .py[co].

    If RECORD is not found, raises an error,
    with possible information from the INSTALLER file.

    https://packaging.python.org/specifications/recording-installed-packages/
    """
    location = dist.location
    assert location is not None, "not installed"

    entries = dist.iter_declared_entries()
    if entries is None:
        raise UninstallMissingRecord(distribution=dist)

    for entry in entries:
        path = os.path.join(location, entry)
        yield path
        if path.endswith(".py"):
            dn, fn = os.path.split(path)
            base = fn[:-3]
            path = os.path.join(dn, base + ".pyc")
            yield path
            path = os.path.join(dn, base + ".pyo")
            yield path


def compact(paths: Iterable[str]) -> Set[str]:
    """Compact a path set to contain the minimal number of paths
    necessary to contain all paths in the set. If /a/path/ and
    /a/path/to/a/file.txt are both in the set, leave only the
    shorter path."""

    sep = os.path.sep
    short_paths: Set[str] = set()
    for path in sorted(paths, key=len):
        should_skip = any(
            path.startswith(shortpath.rstrip("*"))
            and path[len(shortpath.rstrip("*").rstrip(sep))] == sep
            for shortpath in short_paths
        )
        if not should_skip:
            short_paths.add(path)
    return short_paths


def compress_for_rename(paths: Iterable[str]) -> Set[str]:
    """Returns a set containing the paths that need to be renamed.

    This set may include directories when the original sequence of paths
    included every file on disk.
    """
    case_map = {os.path.normcase(p): p for p in paths}
    remaining = set(case_map)
    unchecked = sorted({os.path.split(p)[0] for p in case_map.values()}, key=len)
    wildcards: Set[str] = set()

    def norm_join(*a: str) -> str:
        return os.path.normcase(os.path.join(*a))

    for root in unchecked:
        if any(os.path.normcase(root).startswith(w) for w in wildcards):
            # This directory has already been handled.
            continue

        all_files: Set[str] = set()
        all_subdirs: Set[str] = set()
        for dirname, subdirs, files in os.walk(root):
            all_subdirs.update(norm_join(root, dirname, d) for d in subdirs)
            all_files.update(norm_join(root, dirname, f) for f in files)
        # If all the files we found are in our remaining set of files to
        # remove, then remove them from the latter set and add a wildcard
        # for the directory.
        if not (all_files - remaining):
            remaining.difference_update(all_files)
            wildcards.add(root + os.sep)

    return set(map(case_map.__getitem__, remaining)) | wildcards


def compress_for_output_listing(paths: Iterable[str]) -> Tuple[Set[str], Set[str]]:
    """Returns a tuple of 2 sets of which paths to display to user

    The first set contains paths that would be deleted. Files of a package
    are not added and the top-level directory of the package has a '*' added
    at the end - to signify that all it's contents are removed.

    The second set contains files that would have been skipped in the above
    folders.
    """

    will_remove = set(paths)
    will_skip = set()

    # Determine folders and files
    folders = set()
    files = set()
    for path in will_remove:
        if path.endswith(".pyc"):
            continue
        if path.endswith("__init__.py") or ".dist-info" in path:
            folders.add(os.path.dirname(path))
        files.add(path)

    _normcased_files = set(map(os.path.normcase, files))

    folders = compact(folders)

    # This walks the tree using os.walk to not miss extra folders
    # that might get added.
    for folder in folders:
        for dirpath, _, dirfiles in os.walk(folder):
            for fname in dirfiles:
                if fname.endswith(".pyc"):
                    continue

                file_ = os.path.join(dirpath, fname)
                if (
                    os.path.isfile(file_)
                    and os.path.normcase(file_) not in _normcased_files
                ):
                    # We are skipping this file. Add it to the set.
                    will_skip.add(file_)

    will_remove = files | {os.path.join(folder, "*") for folder in folders}

    return will_remove, will_skip


class StashedUninstallPathSet:
    """A set of file rename operations to stash files while
    tentatively uninstalling them."""

    def __init__(self) -> None:
        # Mapping from source file root to [Adjacent]TempDirectory
        # for files under that directory.
        self._save_dirs: Dict[str, TempDirectory] = {}
        # (old path, new path) tuples for each move that may need
        # to be undone.
        self._moves: List[Tuple[str, str]] = []

    def _get_directory_stash(self, path: str) -> str:
        """Stashes a directory.

        Directories are stashed adjacent to their original location if
        possible, or else moved/copied into the user's temp dir."""

        try:
            save_dir: TempDirectory = AdjacentTempDirectory(path)
        except OSError:
            save_dir = TempDirectory(kind="uninstall")
        self._save_dirs[os.path.normcase(path)] = save_dir

        return save_dir.path

    def _get_file_stash(self, path: str) -> str:
        """Stashes a file.

        If no root has been provided, one will be created for the directory
        in the user's temp directory."""
        path = os.path.normcase(path)
        head, old_head = os.path.dirname(path), None
        save_dir = None

        while head != old_head:
            try:
                save_dir = self._save_dirs[head]
                break
            except KeyError:
                pass
            head, old_head = os.path.dirname(head), head
        else:
            # Did not find any suitable root
            head = os.path.dirname(path)
            save_dir = TempDirectory(kind="uninstall")
            self._save_dirs[head] = save_dir

        relpath = os.path.relpath(path, head)
        if relpath and relpath != os.path.curdir:
            return os.path.join(save_dir.path, relpath)
        return save_dir.path

    def stash(self, path: str) -> str:
        """Stashes the directory or file and returns its new location.
        Handle symlinks as files to avoid modifying the symlink targets.
        """
        path_is_dir = os.path.isdir(path) and not os.path.islink(path)
        if path_is_dir:
            new_path = self._get_directory_stash(path)
        else:
            new_path = self._get_file_stash(path)

        self._moves.append((path, new_path))
        if path_is_dir and os.path.isdir(new_path):
            # If we're moving a directory, we need to
            # remove the destination first or else it will be
            # moved to inside the existing directory.
            # We just created new_path ourselves, so it will
            # be removable.
            os.rmdir(new_path)
        renames(path, new_path)
        return new_path

    def commit(self) -> None:
        """Commits the uninstall by removing stashed files."""
        for save_dir in self._save_dirs.values():
            save_dir.cleanup()
        self._moves = []
        self._save_dirs = {}

    def rollback(self) -> None:
        """Undoes the uninstall by moving stashed files back."""
        for p in self._moves:
            logger.info("Moving to %s\n from %s", *p)

        for new_path, path in self._moves:
            try:
                logger.debug("Replacing %s from %s", new_path, path)
                if os.path.isfile(new_path) or os.path.islink(new_path):
                    os.unlink(new_path)
                elif os.path.isdir(new_path):
                    rmtree(new_path)
                renames(path, new_path)
            except OSError as ex:
                logger.error("Failed to restore %s", new_path)
                logger.debug("Exception: %s", ex)

        self.commit()

    @property
    def can_rollback(self) -> bool:
        return bool(self._moves)


class UninstallPathSet:
    """A set of file paths to be removed in the uninstallation of a
    requirement."""

    def __init__(self, dist: BaseDistribution) -> None:
        self._paths: Set[str] = set()
        self._refuse: Set[str] = set()
        self._pth: Dict[str, UninstallPthEntries] = {}
        self._dist = dist
        self._moved_paths = StashedUninstallPathSet()
        # Create local cache of normalize_path results. Creating an UninstallPathSet
        # can result in hundreds/thousands of redundant calls to normalize_path with
        # the same args, which hurts performance.
        self._normalize_path_cached = functools.lru_cache(normalize_path)

    def _permitted(self, path: str) -> bool:
        """
        Return True if the given path is one we are permitted to
        remove/modify, False otherwise.

        """
        # aka is_local, but caching normalized sys.prefix
        if not running_under_virtualenv():
            return True
        return path.startswith(self._normalize_path_cached(sys.prefix))

    def add(self, path: str) -> None:
        head, tail = os.path.split(path)

        # we normalize the head to resolve parent directory symlinks, but not
        # the tail, since we only want to uninstall symlinks, not their targets
        path = os.path.join(self._normalize_path_cached(head), os.path.normcase(tail))

        if not os.path.exists(path):
            return
        if self._permitted(path):
            self._paths.add(path)
        else:
            self._refuse.add(path)

        # __pycache__ files can show up after 'installed-files.txt' is created,
        # due to imports
        if os.path.splitext(path)[1] == ".py":
            self.add(cache_from_source(path))

    def add_pth(self, pth_file: str, entry: str) -> None:
        pth_file = self._normalize_path_cached(pth_file)
        if self._permitted(pth_file):
            if pth_file not in self._pth:
                self._pth[pth_file] = UninstallPthEntries(pth_file)
            self._pth[pth_file].add(entry)
        else:
            self._refuse.add(pth_file)

    def remove(self, auto_confirm: bool = False, verbose: bool = False) -> None:
        """Remove paths in ``self._paths`` with confirmation (unless
        ``auto_confirm`` is True)."""

        if not self._paths:
            logger.info(
                "Can't uninstall '%s'. No files were found to uninstall.",
                self._dist.raw_name,
            )
            return

        dist_name_version = f"{self._dist.raw_name}-{self._dist.raw_version}"
        logger.info("Uninstalling %s:", dist_name_version)

        with indent_log():
            if auto_confirm or self._allowed_to_proceed(verbose):
                moved = self._moved_paths

                for_rename = compress_for_rename(self._paths)

                for path in sorted(compact(for_rename)):
                    moved.stash(path)
                    logger.verbose("Removing file or directory %s", path)

                for pth in self._pth.values():
                    pth.remove()

                logger.info("Successfully uninstalled %s", dist_name_version)

    def _allowed_to_proceed(self, verbose: bool) -> bool:
        """Display which files would be deleted and prompt for confirmation"""

        def _display(msg: str, paths: Iterable[str]) -> None:
            if not paths:
                return

            logger.info(msg)
            with indent_log():
                for path in sorted(compact(paths)):
                    logger.info(path)

        if not verbose:
            will_remove, will_skip = compress_for_output_listing(self._paths)
        else:
            # In verbose mode, display all the files that are going to be
            # deleted.
            will_remove = set(self._paths)
            will_skip = set()

        _display("Would remove:", will_remove)
        _display("Would not remove (might be manually added):", will_skip)
        _display("Would not remove (outside of prefix):", self._refuse)
        if verbose:
            _display("Will actually move:", compress_for_rename(self._paths))

        return ask("Proceed (Y/n)? ", ("y", "n", "")) != "n"

    def rollback(self) -> None:
        """Rollback the changes previously made by remove()."""
        if not self._moved_paths.can_rollback:
            logger.error(
                "Can't roll back %s; was not uninstalled",
                self._dist.raw_name,
            )
            return
        logger.info("Rolling back uninstall of %s", self._dist.raw_name)
        self._moved_paths.rollback()
        for pth in self._pth.values():
            pth.rollback()

    def commit(self) -> None:
        """Remove temporary save dir: rollback will no longer be possible."""
        self._moved_paths.commit()

    @classmethod
    def from_dist(cls, dist: BaseDistribution) -> "UninstallPathSet":
        dist_location = dist.location
        info_location = dist.info_location
        if dist_location is None:
            logger.info(
                "Not uninstalling %s since it is not installed",
                dist.canonical_name,
            )
            return cls(dist)

        normalized_dist_location = normalize_path(dist_location)
        if not dist.local:
            logger.info(
                "Not uninstalling %s at %s, outside environment %s",
                dist.canonical_name,
                normalized_dist_location,
                sys.prefix,
            )
            return cls(dist)

        if normalized_dist_location in {
            p
            for p in {sysconfig.get_path("stdlib"), sysconfig.get_path("platstdlib")}
            if p
        }:
            logger.info(
                "Not uninstalling %s at %s, as it is in the standard library.",
                dist.canonical_name,
                normalized_dist_location,
            )
            return cls(dist)

        paths_to_remove = cls(dist)
        develop_egg_link = egg_link_path_from_location(dist.raw_name)

        # Distribution is installed with metadata in a "flat" .egg-info
        # directory. This means it is not a modern .dist-info installation, an
        # egg, or legacy editable.
        setuptools_flat_installation = (
            dist.installed_with_setuptools_egg_info
            and info_location is not None
            and os.path.exists(info_location)
            # If dist is editable and the location points to a ``.egg-info``,
            # we are in fact in the legacy editable case.
            and not info_location.endswith(f"{dist.setuptools_filename}.egg-info")
        )

        # Uninstall cases order do matter as in the case of 2 installs of the
        # same package, pip needs to uninstall the currently detected version
        if setuptools_flat_installation:
            if info_location is not None:
                paths_to_remove.add(info_location)
            installed_files = dist.iter_declared_entries()
            if installed_files is not None:
                for installed_file in installed_files:
                    paths_to_remove.add(os.path.join(dist_location, installed_file))
            # FIXME: need a test for this elif block
            # occurs with --single-version-externally-managed/--record outside
            # of pip
            elif dist.is_file("top_level.txt"):
                try:
                    namespace_packages = dist.read_text("namespace_packages.txt")
                except FileNotFoundError:
                    namespaces = []
                else:
                    namespaces = namespace_packages.splitlines(keepends=False)
                for top_level_pkg in [
                    p
                    for p in dist.read_text("top_level.txt").splitlines()
                    if p and p not in namespaces
                ]:
                    path = os.path.join(dist_location, top_level_pkg)
                    paths_to_remove.add(path)
                    paths_to_remove.add(f"{path}.py")
                    paths_to_remove.add(f"{path}.pyc")
                    paths_to_remove.add(f"{path}.pyo")

        elif dist.installed_by_distutils:
            raise LegacyDistutilsInstall(distribution=dist)

        elif dist.installed_as_egg:
            # package installed by easy_install
            # We cannot match on dist.egg_name because it can slightly vary
            # i.e. setuptools-0.6c11-py2.6.egg vs setuptools-0.6rc11-py2.6.egg
            paths_to_remove.add(dist_location)
            easy_install_egg = os.path.split(dist_location)[1]
            easy_install_pth = os.path.join(
                os.path.dirname(dist_location),
                "easy-install.pth",
            )
            paths_to_remove.add_pth(easy_install_pth, "./" + easy_install_egg)

        elif dist.installed_with_dist_info:
            for path in uninstallation_paths(dist):
                paths_to_remove.add(path)

        elif develop_egg_link:
            # PEP 660 modern editable is handled in the ``.dist-info`` case
            # above, so this only covers the setuptools-style editable.
            with open(develop_egg_link) as fh:
                link_pointer = os.path.normcase(fh.readline().strip())
                normalized_link_pointer = paths_to_remove._normalize_path_cached(
                    link_pointer
                )
            assert os.path.samefile(
                normalized_link_pointer, normalized_dist_location
            ), (
                f"Egg-link {develop_egg_link} (to {link_pointer}) does not match "
                f"installed location of {dist.raw_name} (at {dist_location})"
            )
            paths_to_remove.add(develop_egg_link)
            easy_install_pth = os.path.join(
                os.path.dirname(develop_egg_link), "easy-install.pth"
            )
            paths_to_remove.add_pth(easy_install_pth, dist_location)

        else:
            logger.debug(
                "Not sure how to uninstall: %s - Check: %s",
                dist,
                dist_location,
            )

        if dist.in_usersite:
            bin_dir = get_bin_user()
        else:
            bin_dir = get_bin_prefix()

        # find distutils scripts= scripts
        try:
            for script in dist.iter_distutils_script_names():
                paths_to_remove.add(os.path.join(bin_dir, script))
                if WINDOWS:
                    paths_to_remove.add(os.path.join(bin_dir, f"{script}.bat"))
        except (FileNotFoundError, NotADirectoryError):
            pass

        # find console_scripts and gui_scripts
        def iter_scripts_to_remove(
            dist: BaseDistribution,
            bin_dir: str,
        ) -> Generator[str, None, None]:
            for entry_point in dist.iter_entry_points():
                if entry_point.group == "console_scripts":
                    yield from _script_names(bin_dir, entry_point.name, False)
                elif entry_point.group == "gui_scripts":
                    yield from _script_names(bin_dir, entry_point.name, True)

        for s in iter_scripts_to_remove(dist, bin_dir):
            paths_to_remove.add(s)

        return paths_to_remove


class UninstallPthEntries:
    def __init__(self, pth_file: str) -> None:
        self.file = pth_file
        self.entries: Set[str] = set()
        self._saved_lines: Optional[List[bytes]] = None

    def add(self, entry: str) -> None:
        entry = os.path.normcase(entry)
        # On Windows, os.path.normcase converts the entry to use
        # backslashes.  This is correct for entries that describe absolute
        # paths outside of site-packages, but all the others use forward
        # slashes.
        # os.path.splitdrive is used instead of os.path.isabs because isabs
        # treats non-absolute paths with drive letter markings like c:foo\bar
        # as absolute paths. It also does not recognize UNC paths if they don't
        # have more than "\\sever\share". Valid examples: "\\server\share\" or
        # "\\server\share\folder".
        if WINDOWS and not os.path.splitdrive(entry)[0]:
            entry = entry.replace("\\", "/")
        self.entries.add(entry)

    def remove(self) -> None:
        logger.verbose("Removing pth entries from %s:", self.file)

        # If the file doesn't exist, log a warning and return
        if not os.path.isfile(self.file):
            logger.warning("Cannot remove entries from nonexistent file %s", self.file)
            return
        with open(self.file, "rb") as fh:
            # windows uses '\r\n' with py3k, but uses '\n' with py2.x
            lines = fh.readlines()
            self._saved_lines = lines
        if any(b"\r\n" in line for line in lines):
            endline = "\r\n"
        else:
            endline = "\n"
        # handle missing trailing newline
        if lines and not lines[-1].endswith(endline.encode("utf-8")):
            lines[-1] = lines[-1] + endline.encode("utf-8")
        for entry in self.entries:
            try:
                logger.verbose("Removing entry: %s", entry)
                lines.remove((entry + endline).encode("utf-8"))
            except ValueError:
                pass
        with open(self.file, "wb") as fh:
            fh.writelines(lines)

    def rollback(self) -> bool:
        if self._saved_lines is None:
            logger.error("Cannot roll back changes to %s, none were made", self.file)
            return False
        logger.debug("Rolling %s back to previous state", self.file)
        with open(self.file, "wb") as fh:
            fh.writelines(self._saved_lines)
        return True
634 lines•23.3 KB
python
.venv/Lib/site-packages/pip/_vendor/requests/adapters.py
Raw Download
Find: Go to:
"""
requests.adapters
~~~~~~~~~~~~~~~~~

This module contains the transport adapters that Requests uses to define
and maintain connections.
"""

import os.path
import socket  # noqa: F401
import typing
import warnings

from pip._vendor.urllib3.exceptions import ClosedPoolError, ConnectTimeoutError
from pip._vendor.urllib3.exceptions import HTTPError as _HTTPError
from pip._vendor.urllib3.exceptions import InvalidHeader as _InvalidHeader
from pip._vendor.urllib3.exceptions import (
    LocationValueError,
    MaxRetryError,
    NewConnectionError,
    ProtocolError,
)
from pip._vendor.urllib3.exceptions import ProxyError as _ProxyError
from pip._vendor.urllib3.exceptions import ReadTimeoutError, ResponseError
from pip._vendor.urllib3.exceptions import SSLError as _SSLError
from pip._vendor.urllib3.poolmanager import PoolManager, proxy_from_url
from pip._vendor.urllib3.util import Timeout as TimeoutSauce
from pip._vendor.urllib3.util import parse_url
from pip._vendor.urllib3.util.retry import Retry
from pip._vendor.urllib3.util.ssl_ import create_urllib3_context

from .auth import _basic_auth_str
from .compat import basestring, urlparse
from .cookies import extract_cookies_to_jar
from .exceptions import (
    ConnectionError,
    ConnectTimeout,
    InvalidHeader,
    InvalidProxyURL,
    InvalidSchema,
    InvalidURL,
    ProxyError,
    ReadTimeout,
    RetryError,
    SSLError,
)
from .models import Response
from .structures import CaseInsensitiveDict
from .utils import (
    DEFAULT_CA_BUNDLE_PATH,
    extract_zipped_paths,
    get_auth_from_url,
    get_encoding_from_headers,
    prepend_scheme_if_needed,
    select_proxy,
    urldefragauth,
)

try:
    from pip._vendor.urllib3.contrib.socks import SOCKSProxyManager
except ImportError:

    def SOCKSProxyManager(*args, **kwargs):
        raise InvalidSchema("Missing dependencies for SOCKS support.")


if typing.TYPE_CHECKING:
    from .models import PreparedRequest


DEFAULT_POOLBLOCK = False
DEFAULT_POOLSIZE = 10
DEFAULT_RETRIES = 0
DEFAULT_POOL_TIMEOUT = None


try:
    import ssl  # noqa: F401

    _preloaded_ssl_context = create_urllib3_context()
    _preloaded_ssl_context.load_verify_locations(
        extract_zipped_paths(DEFAULT_CA_BUNDLE_PATH)
    )
except ImportError:
    # Bypass default SSLContext creation when Python
    # interpreter isn't built with the ssl module.
    _preloaded_ssl_context = None


def _urllib3_request_context(
    request: "PreparedRequest",
    verify: "bool | str | None",
    client_cert: "typing.Tuple[str, str] | str | None",
    poolmanager: "PoolManager",
) -> "(typing.Dict[str, typing.Any], typing.Dict[str, typing.Any])":
    host_params = {}
    pool_kwargs = {}
    parsed_request_url = urlparse(request.url)
    scheme = parsed_request_url.scheme.lower()
    port = parsed_request_url.port

    # Determine if we have and should use our default SSLContext
    # to optimize performance on standard requests.
    poolmanager_kwargs = getattr(poolmanager, "connection_pool_kw", {})
    has_poolmanager_ssl_context = poolmanager_kwargs.get("ssl_context")
    should_use_default_ssl_context = (
        _preloaded_ssl_context is not None and not has_poolmanager_ssl_context
    )

    cert_reqs = "CERT_REQUIRED"
    if verify is False:
        cert_reqs = "CERT_NONE"
    elif verify is True and should_use_default_ssl_context:
        pool_kwargs["ssl_context"] = _preloaded_ssl_context
    elif isinstance(verify, str):
        if not os.path.isdir(verify):
            pool_kwargs["ca_certs"] = verify
        else:
            pool_kwargs["ca_cert_dir"] = verify
    pool_kwargs["cert_reqs"] = cert_reqs
    if client_cert is not None:
        if isinstance(client_cert, tuple) and len(client_cert) == 2:
            pool_kwargs["cert_file"] = client_cert[0]
            pool_kwargs["key_file"] = client_cert[1]
        else:
            # According to our docs, we allow users to specify just the client
            # cert path
            pool_kwargs["cert_file"] = client_cert
    host_params = {
        "scheme": scheme,
        "host": parsed_request_url.hostname,
        "port": port,
    }
    return host_params, pool_kwargs


class BaseAdapter:
    """The Base Transport Adapter"""

    def __init__(self):
        super().__init__()

    def send(
        self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
    ):
        """Sends PreparedRequest object. Returns Response object.

        :param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
        :param stream: (optional) Whether to stream the request content.
        :param timeout: (optional) How long to wait for the server to send
            data before giving up, as a float, or a :ref:`(connect timeout,
            read timeout) <timeouts>` tuple.
        :type timeout: float or tuple
        :param verify: (optional) Either a boolean, in which case it controls whether we verify
            the server's TLS certificate, or a string, in which case it must be a path
            to a CA bundle to use
        :param cert: (optional) Any user-provided SSL certificate to be trusted.
        :param proxies: (optional) The proxies dictionary to apply to the request.
        """
        raise NotImplementedError

    def close(self):
        """Cleans up adapter specific items."""
        raise NotImplementedError


class HTTPAdapter(BaseAdapter):
    """The built-in HTTP Adapter for urllib3.

    Provides a general-case interface for Requests sessions to contact HTTP and
    HTTPS urls by implementing the Transport Adapter interface. This class will
    usually be created by the :class:`Session <Session>` class under the
    covers.

    :param pool_connections: The number of urllib3 connection pools to cache.
    :param pool_maxsize: The maximum number of connections to save in the pool.
    :param max_retries: The maximum number of retries each connection
        should attempt. Note, this applies only to failed DNS lookups, socket
        connections and connection timeouts, never to requests where data has
        made it to the server. By default, Requests does not retry failed
        connections. If you need granular control over the conditions under
        which we retry a request, import urllib3's ``Retry`` class and pass
        that instead.
    :param pool_block: Whether the connection pool should block for connections.

    Usage::

      >>> import requests
      >>> s = requests.Session()
      >>> a = requests.adapters.HTTPAdapter(max_retries=3)
      >>> s.mount('http://', a)
    """

    __attrs__ = [
        "max_retries",
        "config",
        "_pool_connections",
        "_pool_maxsize",
        "_pool_block",
    ]

    def __init__(
        self,
        pool_connections=DEFAULT_POOLSIZE,
        pool_maxsize=DEFAULT_POOLSIZE,
        max_retries=DEFAULT_RETRIES,
        pool_block=DEFAULT_POOLBLOCK,
    ):
        if max_retries == DEFAULT_RETRIES:
            self.max_retries = Retry(0, read=False)
        else:
            self.max_retries = Retry.from_int(max_retries)
        self.config = {}
        self.proxy_manager = {}

        super().__init__()

        self._pool_connections = pool_connections
        self._pool_maxsize = pool_maxsize
        self._pool_block = pool_block

        self.init_poolmanager(pool_connections, pool_maxsize, block=pool_block)

    def __getstate__(self):
        return {attr: getattr(self, attr, None) for attr in self.__attrs__}

    def __setstate__(self, state):
        # Can't handle by adding 'proxy_manager' to self.__attrs__ because
        # self.poolmanager uses a lambda function, which isn't pickleable.
        self.proxy_manager = {}
        self.config = {}

        for attr, value in state.items():
            setattr(self, attr, value)

        self.init_poolmanager(
            self._pool_connections, self._pool_maxsize, block=self._pool_block
        )

    def init_poolmanager(
        self, connections, maxsize, block=DEFAULT_POOLBLOCK, **pool_kwargs
    ):
        """Initializes a urllib3 PoolManager.

        This method should not be called from user code, and is only
        exposed for use when subclassing the
        :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.

        :param connections: The number of urllib3 connection pools to cache.
        :param maxsize: The maximum number of connections to save in the pool.
        :param block: Block when no free connections are available.
        :param pool_kwargs: Extra keyword arguments used to initialize the Pool Manager.
        """
        # save these values for pickling
        self._pool_connections = connections
        self._pool_maxsize = maxsize
        self._pool_block = block

        self.poolmanager = PoolManager(
            num_pools=connections,
            maxsize=maxsize,
            block=block,
            **pool_kwargs,
        )

    def proxy_manager_for(self, proxy, **proxy_kwargs):
        """Return urllib3 ProxyManager for the given proxy.

        This method should not be called from user code, and is only
        exposed for use when subclassing the
        :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.

        :param proxy: The proxy to return a urllib3 ProxyManager for.
        :param proxy_kwargs: Extra keyword arguments used to configure the Proxy Manager.
        :returns: ProxyManager
        :rtype: urllib3.ProxyManager
        """
        if proxy in self.proxy_manager:
            manager = self.proxy_manager[proxy]
        elif proxy.lower().startswith("socks"):
            username, password = get_auth_from_url(proxy)
            manager = self.proxy_manager[proxy] = SOCKSProxyManager(
                proxy,
                username=username,
                password=password,
                num_pools=self._pool_connections,
                maxsize=self._pool_maxsize,
                block=self._pool_block,
                **proxy_kwargs,
            )
        else:
            proxy_headers = self.proxy_headers(proxy)
            manager = self.proxy_manager[proxy] = proxy_from_url(
                proxy,
                proxy_headers=proxy_headers,
                num_pools=self._pool_connections,
                maxsize=self._pool_maxsize,
                block=self._pool_block,
                **proxy_kwargs,
            )

        return manager

    def cert_verify(self, conn, url, verify, cert):
        """Verify a SSL certificate. This method should not be called from user
        code, and is only exposed for use when subclassing the
        :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.

        :param conn: The urllib3 connection object associated with the cert.
        :param url: The requested URL.
        :param verify: Either a boolean, in which case it controls whether we verify
            the server's TLS certificate, or a string, in which case it must be a path
            to a CA bundle to use
        :param cert: The SSL certificate to verify.
        """
        if url.lower().startswith("https") and verify:
            conn.cert_reqs = "CERT_REQUIRED"

            # Only load the CA certificates if 'verify' is a string indicating the CA bundle to use.
            # Otherwise, if verify is a boolean, we don't load anything since
            # the connection will be using a context with the default certificates already loaded,
            # and this avoids a call to the slow load_verify_locations()
            if verify is not True:
                # `verify` must be a str with a path then
                cert_loc = verify

                if not os.path.exists(cert_loc):
                    raise OSError(
                        f"Could not find a suitable TLS CA certificate bundle, "
                        f"invalid path: {cert_loc}"
                    )

                if not os.path.isdir(cert_loc):
                    conn.ca_certs = cert_loc
                else:
                    conn.ca_cert_dir = cert_loc
        else:
            conn.cert_reqs = "CERT_NONE"
            conn.ca_certs = None
            conn.ca_cert_dir = None

        if cert:
            if not isinstance(cert, basestring):
                conn.cert_file = cert[0]
                conn.key_file = cert[1]
            else:
                conn.cert_file = cert
                conn.key_file = None
            if conn.cert_file and not os.path.exists(conn.cert_file):
                raise OSError(
                    f"Could not find the TLS certificate file, "
                    f"invalid path: {conn.cert_file}"
                )
            if conn.key_file and not os.path.exists(conn.key_file):
                raise OSError(
                    f"Could not find the TLS key file, invalid path: {conn.key_file}"
                )

    def build_response(self, req, resp):
        """Builds a :class:`Response <requests.Response>` object from a urllib3
        response. This should not be called from user code, and is only exposed
        for use when subclassing the
        :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`

        :param req: The :class:`PreparedRequest <PreparedRequest>` used to generate the response.
        :param resp: The urllib3 response object.
        :rtype: requests.Response
        """
        response = Response()

        # Fallback to None if there's no status_code, for whatever reason.
        response.status_code = getattr(resp, "status", None)

        # Make headers case-insensitive.
        response.headers = CaseInsensitiveDict(getattr(resp, "headers", {}))

        # Set encoding.
        response.encoding = get_encoding_from_headers(response.headers)
        response.raw = resp
        response.reason = response.raw.reason

        if isinstance(req.url, bytes):
            response.url = req.url.decode("utf-8")
        else:
            response.url = req.url

        # Add new cookies from the server.
        extract_cookies_to_jar(response.cookies, req, resp)

        # Give the Response some context.
        response.request = req
        response.connection = self

        return response

    def build_connection_pool_key_attributes(self, request, verify, cert=None):
        """Build the PoolKey attributes used by urllib3 to return a connection.

        This looks at the PreparedRequest, the user-specified verify value,
        and the value of the cert parameter to determine what PoolKey values
        to use to select a connection from a given urllib3 Connection Pool.

        The SSL related pool key arguments are not consistently set. As of
        this writing, use the following to determine what keys may be in that
        dictionary:

        * If ``verify`` is ``True``, ``"ssl_context"`` will be set and will be the
          default Requests SSL Context
        * If ``verify`` is ``False``, ``"ssl_context"`` will not be set but
          ``"cert_reqs"`` will be set
        * If ``verify`` is a string, (i.e., it is a user-specified trust bundle)
          ``"ca_certs"`` will be set if the string is not a directory recognized
          by :py:func:`os.path.isdir`, otherwise ``"ca_certs_dir"`` will be
          set.
        * If ``"cert"`` is specified, ``"cert_file"`` will always be set. If
          ``"cert"`` is a tuple with a second item, ``"key_file"`` will also
          be present

        To override these settings, one may subclass this class, call this
        method and use the above logic to change parameters as desired. For
        example, if one wishes to use a custom :py:class:`ssl.SSLContext` one
        must both set ``"ssl_context"`` and based on what else they require,
        alter the other keys to ensure the desired behaviour.

        :param request:
            The PreparedReqest being sent over the connection.
        :type request:
            :class:`~requests.models.PreparedRequest`
        :param verify:
            Either a boolean, in which case it controls whether
            we verify the server's TLS certificate, or a string, in which case it
            must be a path to a CA bundle to use.
        :param cert:
            (optional) Any user-provided SSL certificate for client
            authentication (a.k.a., mTLS). This may be a string (i.e., just
            the path to a file which holds both certificate and key) or a
            tuple of length 2 with the certificate file path and key file
            path.
        :returns:
            A tuple of two dictionaries. The first is the "host parameters"
            portion of the Pool Key including scheme, hostname, and port. The
            second is a dictionary of SSLContext related parameters.
        """
        return _urllib3_request_context(request, verify, cert, self.poolmanager)

    def get_connection_with_tls_context(self, request, verify, proxies=None, cert=None):
        """Returns a urllib3 connection for the given request and TLS settings.
        This should not be called from user code, and is only exposed for use
        when subclassing the :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.

        :param request:
            The :class:`PreparedRequest <PreparedRequest>` object to be sent
            over the connection.
        :param verify:
            Either a boolean, in which case it controls whether we verify the
            server's TLS certificate, or a string, in which case it must be a
            path to a CA bundle to use.
        :param proxies:
            (optional) The proxies dictionary to apply to the request.
        :param cert:
            (optional) Any user-provided SSL certificate to be used for client
            authentication (a.k.a., mTLS).
        :rtype:
            urllib3.ConnectionPool
        """
        proxy = select_proxy(request.url, proxies)
        try:
            host_params, pool_kwargs = self.build_connection_pool_key_attributes(
                request,
                verify,
                cert,
            )
        except ValueError as e:
            raise InvalidURL(e, request=request)
        if proxy:
            proxy = prepend_scheme_if_needed(proxy, "http")
            proxy_url = parse_url(proxy)
            if not proxy_url.host:
                raise InvalidProxyURL(
                    "Please check proxy URL. It is malformed "
                    "and could be missing the host."
                )
            proxy_manager = self.proxy_manager_for(proxy)
            conn = proxy_manager.connection_from_host(
                **host_params, pool_kwargs=pool_kwargs
            )
        else:
            # Only scheme should be lower case
            conn = self.poolmanager.connection_from_host(
                **host_params, pool_kwargs=pool_kwargs
            )

        return conn

    def get_connection(self, url, proxies=None):
        """DEPRECATED: Users should move to `get_connection_with_tls_context`
        for all subclasses of HTTPAdapter using Requests>=2.32.2.

        Returns a urllib3 connection for the given URL. This should not be
        called from user code, and is only exposed for use when subclassing the
        :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.

        :param url: The URL to connect to.
        :param proxies: (optional) A Requests-style dictionary of proxies used on this request.
        :rtype: urllib3.ConnectionPool
        """
        warnings.warn(
            (
                "`get_connection` has been deprecated in favor of "
                "`get_connection_with_tls_context`. Custom HTTPAdapter subclasses "
                "will need to migrate for Requests>=2.32.2. Please see "
                "https://github.com/psf/requests/pull/6710 for more details."
            ),
            DeprecationWarning,
        )
        proxy = select_proxy(url, proxies)

        if proxy:
            proxy = prepend_scheme_if_needed(proxy, "http")
            proxy_url = parse_url(proxy)
            if not proxy_url.host:
                raise InvalidProxyURL(
                    "Please check proxy URL. It is malformed "
                    "and could be missing the host."
                )
            proxy_manager = self.proxy_manager_for(proxy)
            conn = proxy_manager.connection_from_url(url)
        else:
            # Only scheme should be lower case
            parsed = urlparse(url)
            url = parsed.geturl()
            conn = self.poolmanager.connection_from_url(url)

        return conn

    def close(self):
        """Disposes of any internal state.

        Currently, this closes the PoolManager and any active ProxyManager,
        which closes any pooled connections.
        """
        self.poolmanager.clear()
        for proxy in self.proxy_manager.values():
            proxy.clear()

    def request_url(self, request, proxies):
        """Obtain the url to use when making the final request.

        If the message is being sent through a HTTP proxy, the full URL has to
        be used. Otherwise, we should only use the path portion of the URL.

        This should not be called from user code, and is only exposed for use
        when subclassing the
        :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.

        :param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
        :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs.
        :rtype: str
        """
        proxy = select_proxy(request.url, proxies)
        scheme = urlparse(request.url).scheme

        is_proxied_http_request = proxy and scheme != "https"
        using_socks_proxy = False
        if proxy:
            proxy_scheme = urlparse(proxy).scheme.lower()
            using_socks_proxy = proxy_scheme.startswith("socks")

        url = request.path_url
        if url.startswith("//"):  # Don't confuse urllib3
            url = f"/{url.lstrip('/')}"

        if is_proxied_http_request and not using_socks_proxy:
            url = urldefragauth(request.url)

        return url

    def add_headers(self, request, **kwargs):
        """Add any headers needed by the connection. As of v2.0 this does
        nothing by default, but is left for overriding by users that subclass
        the :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.

        This should not be called from user code, and is only exposed for use
        when subclassing the
        :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.

        :param request: The :class:`PreparedRequest <PreparedRequest>` to add headers to.
        :param kwargs: The keyword arguments from the call to send().
        """
        pass

    def proxy_headers(self, proxy):
        """Returns a dictionary of the headers to add to any request sent
        through a proxy. This works with urllib3 magic to ensure that they are
        correctly sent to the proxy, rather than in a tunnelled request if
        CONNECT is being used.

        This should not be called from user code, and is only exposed for use
        when subclassing the
        :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.

        :param proxy: The url of the proxy being used for this request.
        :rtype: dict
        """
        headers = {}
        username, password = get_auth_from_url(proxy)

        if username:
            headers["Proxy-Authorization"] = _basic_auth_str(username, password)

        return headers

    def send(
        self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
    ):
        """Sends PreparedRequest object. Returns Response object.

        :param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
        :param stream: (optional) Whether to stream the request content.
        :param timeout: (optional) How long to wait for the server to send
            data before giving up, as a float, or a :ref:`(connect timeout,
            read timeout) <timeouts>` tuple.
        :type timeout: float or tuple or urllib3 Timeout object
        :param verify: (optional) Either a boolean, in which case it controls whether
            we verify the server's TLS certificate, or a string, in which case it
            must be a path to a CA bundle to use
        :param cert: (optional) Any user-provided SSL certificate to be trusted.
        :param proxies: (optional) The proxies dictionary to apply to the request.
        :rtype: requests.Response
        """

        try:
            conn = self.get_connection_with_tls_context(
                request, verify, proxies=proxies, cert=cert
            )
        except LocationValueError as e:
            raise InvalidURL(e, request=request)

        self.cert_verify(conn, request.url, verify, cert)
        url = self.request_url(request, proxies)
        self.add_headers(
            request,
            stream=stream,
            timeout=timeout,
            verify=verify,
            cert=cert,
            proxies=proxies,
        )

        chunked = not (request.body is None or "Content-Length" in request.headers)

        if isinstance(timeout, tuple):
            try:
                connect, read = timeout
                timeout = TimeoutSauce(connect=connect, read=read)
            except ValueError:
                raise ValueError(
                    f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
                    f"or a single float to set both timeouts to the same value."
                )
        elif isinstance(timeout, TimeoutSauce):
            pass
        else:
            timeout = TimeoutSauce(connect=timeout, read=timeout)

        try:
            resp = conn.urlopen(
                method=request.method,
                url=url,
                body=request.body,
                headers=request.headers,
                redirect=False,
                assert_same_host=False,
                preload_content=False,
                decode_content=False,
                retries=self.max_retries,
                timeout=timeout,
                chunked=chunked,
            )

        except (ProtocolError, OSError) as err:
            raise ConnectionError(err, request=request)

        except MaxRetryError as e:
            if isinstance(e.reason, ConnectTimeoutError):
                # TODO: Remove this in 3.0.0: see #2811
                if not isinstance(e.reason, NewConnectionError):
                    raise ConnectTimeout(e, request=request)

            if isinstance(e.reason, ResponseError):
                raise RetryError(e, request=request)

            if isinstance(e.reason, _ProxyError):
                raise ProxyError(e, request=request)

            if isinstance(e.reason, _SSLError):
                # This branch is for urllib3 v1.22 and later.
                raise SSLError(e, request=request)

            raise ConnectionError(e, request=request)

        except ClosedPoolError as e:
            raise ConnectionError(e, request=request)

        except _ProxyError as e:
            raise ProxyError(e)

        except (_SSLError, _HTTPError) as e:
            if isinstance(e, _SSLError):
                # This branch is for urllib3 versions earlier than v1.22
                raise SSLError(e, request=request)
            elif isinstance(e, ReadTimeoutError):
                raise ReadTimeout(e, request=request)
            elif isinstance(e, _InvalidHeader):
                raise InvalidHeader(e, request=request)
            else:
                raise

        return self.build_response(request, resp)
720 lines•27 KB
python
.venv/Lib/site-packages/pip/_vendor/rich/_emoji_replace.py
Raw Download
Find: Go to:
from typing import Callable, Match, Optional
import re

from ._emoji_codes import EMOJI


_ReStringMatch = Match[str]  # regex match object
_ReSubCallable = Callable[[_ReStringMatch], str]  # Callable invoked by re.sub
_EmojiSubMethod = Callable[[_ReSubCallable, str], str]  # Sub method of a compiled re


def _emoji_replace(
    text: str,
    default_variant: Optional[str] = None,
    _emoji_sub: _EmojiSubMethod = re.compile(r"(:(\S*?)(?:(?:\-)(emoji|text))?:)").sub,
) -> str:
    """Replace emoji code in text."""
    get_emoji = EMOJI.__getitem__
    variants = {"text": "\uFE0E", "emoji": "\uFE0F"}
    get_variant = variants.get
    default_variant_code = variants.get(default_variant, "") if default_variant else ""

    def do_replace(match: Match[str]) -> str:
        emoji_code, emoji_name, variant = match.groups()
        try:
            return get_emoji(emoji_name.lower()) + get_variant(
                variant, default_variant_code
            )
        except KeyError:
            return emoji_code

    return _emoji_sub(do_replace, text)
33 lines•1 KB
python
.venv/Lib/site-packages/pip/_vendor/rich/status.py
Raw Download
Find: Go to:
from types import TracebackType
from typing import Optional, Type

from .console import Console, RenderableType
from .jupyter import JupyterMixin
from .live import Live
from .spinner import Spinner
from .style import StyleType


class Status(JupyterMixin):
    """Displays a status indicator with a 'spinner' animation.

    Args:
        status (RenderableType): A status renderable (str or Text typically).
        console (Console, optional): Console instance to use, or None for global console. Defaults to None.
        spinner (str, optional): Name of spinner animation (see python -m rich.spinner). Defaults to "dots".
        spinner_style (StyleType, optional): Style of spinner. Defaults to "status.spinner".
        speed (float, optional): Speed factor for spinner animation. Defaults to 1.0.
        refresh_per_second (float, optional): Number of refreshes per second. Defaults to 12.5.
    """

    def __init__(
        self,
        status: RenderableType,
        *,
        console: Optional[Console] = None,
        spinner: str = "dots",
        spinner_style: StyleType = "status.spinner",
        speed: float = 1.0,
        refresh_per_second: float = 12.5,
    ):
        self.status = status
        self.spinner_style = spinner_style
        self.speed = speed
        self._spinner = Spinner(spinner, text=status, style=spinner_style, speed=speed)
        self._live = Live(
            self.renderable,
            console=console,
            refresh_per_second=refresh_per_second,
            transient=True,
        )

    @property
    def renderable(self) -> Spinner:
        return self._spinner

    @property
    def console(self) -> "Console":
        """Get the Console used by the Status objects."""
        return self._live.console

    def update(
        self,
        status: Optional[RenderableType] = None,
        *,
        spinner: Optional[str] = None,
        spinner_style: Optional[StyleType] = None,
        speed: Optional[float] = None,
    ) -> None:
        """Update status.

        Args:
            status (Optional[RenderableType], optional): New status renderable or None for no change. Defaults to None.
            spinner (Optional[str], optional): New spinner or None for no change. Defaults to None.
            spinner_style (Optional[StyleType], optional): New spinner style or None for no change. Defaults to None.
            speed (Optional[float], optional): Speed factor for spinner animation or None for no change. Defaults to None.
        """
        if status is not None:
            self.status = status
        if spinner_style is not None:
            self.spinner_style = spinner_style
        if speed is not None:
            self.speed = speed
        if spinner is not None:
            self._spinner = Spinner(
                spinner, text=self.status, style=self.spinner_style, speed=self.speed
            )
            self._live.update(self.renderable, refresh=True)
        else:
            self._spinner.update(
                text=self.status, style=self.spinner_style, speed=self.speed
            )

    def start(self) -> None:
        """Start the status animation."""
        self._live.start()

    def stop(self) -> None:
        """Stop the spinner animation."""
        self._live.stop()

    def __rich__(self) -> RenderableType:
        return self.renderable

    def __enter__(self) -> "Status":
        self.start()
        return self

    def __exit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc_val: Optional[BaseException],
        exc_tb: Optional[TracebackType],
    ) -> None:
        self.stop()


if __name__ == "__main__":  # pragma: no cover
    from time import sleep

    from .console import Console

    console = Console()
    with console.status("[magenta]Covid detector booting up") as status:
        sleep(3)
        console.log("Importing advanced AI")
        sleep(3)
        console.log("Advanced Covid AI Ready")
        sleep(3)
        status.update(status="[bold blue] Scanning for Covid", spinner="earth")
        sleep(3)
        console.log("Found 10,000,000,000 copies of Covid32.exe")
        sleep(3)
        status.update(
            status="[bold red]Moving Covid32.exe to Trash",
            spinner="bouncingBall",
            spinner_style="yellow",
        )
        sleep(5)
    console.print("[bold green]Covid deleted successfully")
132 lines•4.3 KB
python
.venv/Lib/site-packages/pip/_vendor/rich/filesize.py
Raw Download
Find: Go to:
# coding: utf-8
"""Functions for reporting filesizes. Borrowed from https://github.com/PyFilesystem/pyfilesystem2

The functions declared in this module should cover the different
use cases needed to generate a string representation of a file size
using several different units. Since there are many standards regarding
file size units, three different functions have been implemented.

See Also:
    * `Wikipedia: Binary prefix <https://en.wikipedia.org/wiki/Binary_prefix>`_

"""

__all__ = ["decimal"]

from typing import Iterable, List, Optional, Tuple


def _to_str(
    size: int,
    suffixes: Iterable[str],
    base: int,
    *,
    precision: Optional[int] = 1,
    separator: Optional[str] = " ",
) -> str:
    if size == 1:
        return "1 byte"
    elif size < base:
        return "{:,} bytes".format(size)

    for i, suffix in enumerate(suffixes, 2):  # noqa: B007
        unit = base**i
        if size < unit:
            break
    return "{:,.{precision}f}{separator}{}".format(
        (base * size / unit),
        suffix,
        precision=precision,
        separator=separator,
    )


def pick_unit_and_suffix(size: int, suffixes: List[str], base: int) -> Tuple[int, str]:
    """Pick a suffix and base for the given size."""
    for i, suffix in enumerate(suffixes):
        unit = base**i
        if size < unit * base:
            break
    return unit, suffix


def decimal(
    size: int,
    *,
    precision: Optional[int] = 1,
    separator: Optional[str] = " ",
) -> str:
    """Convert a filesize in to a string (powers of 1000, SI prefixes).

    In this convention, ``1000 B = 1 kB``.

    This is typically the format used to advertise the storage
    capacity of USB flash drives and the like (*256 MB* meaning
    actually a storage capacity of more than *256 000 000 B*),
    or used by **Mac OS X** since v10.6 to report file sizes.

    Arguments:
        int (size): A file size.
        int (precision): The number of decimal places to include (default = 1).
        str (separator): The string to separate the value from the units (default = " ").

    Returns:
        `str`: A string containing a abbreviated file size and units.

    Example:
        >>> filesize.decimal(30000)
        '30.0 kB'
        >>> filesize.decimal(30000, precision=2, separator="")
        '30.00kB'

    """
    return _to_str(
        size,
        ("kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"),
        1000,
        precision=precision,
        separator=separator,
    )
90 lines•2.4 KB
python
.venv/Lib/site-packages/pip/_vendor/distro/__init__.py
Raw Download
Find: Go to:
from .distro import (
    NORMALIZED_DISTRO_ID,
    NORMALIZED_LSB_ID,
    NORMALIZED_OS_ID,
    LinuxDistribution,
    __version__,
    build_number,
    codename,
    distro_release_attr,
    distro_release_info,
    id,
    info,
    like,
    linux_distribution,
    lsb_release_attr,
    lsb_release_info,
    major_version,
    minor_version,
    name,
    os_release_attr,
    os_release_info,
    uname_attr,
    uname_info,
    version,
    version_parts,
)

__all__ = [
    "NORMALIZED_DISTRO_ID",
    "NORMALIZED_LSB_ID",
    "NORMALIZED_OS_ID",
    "LinuxDistribution",
    "build_number",
    "codename",
    "distro_release_attr",
    "distro_release_info",
    "id",
    "info",
    "like",
    "linux_distribution",
    "lsb_release_attr",
    "lsb_release_info",
    "major_version",
    "minor_version",
    "name",
    "os_release_attr",
    "os_release_info",
    "uname_attr",
    "uname_info",
    "version",
    "version_parts",
]

__version__ = __version__
55 lines•981 B
python
.venv/Lib/site-packages/pip/_vendor/idna/uts46data.py
Raw Download
Find: Go to:
# This file is automatically generated by tools/idna-data
# vim: set fileencoding=utf-8 :

from typing import List, Tuple, Union


"""IDNA Mapping Table from UTS46."""


__version__ = '15.1.0'
def _seg_0() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x0, '3'),
    (0x1, '3'),
    (0x2, '3'),
    (0x3, '3'),
    (0x4, '3'),
    (0x5, '3'),
    (0x6, '3'),
    (0x7, '3'),
    (0x8, '3'),
    (0x9, '3'),
    (0xA, '3'),
    (0xB, '3'),
    (0xC, '3'),
    (0xD, '3'),
    (0xE, '3'),
    (0xF, '3'),
    (0x10, '3'),
    (0x11, '3'),
    (0x12, '3'),
    (0x13, '3'),
    (0x14, '3'),
    (0x15, '3'),
    (0x16, '3'),
    (0x17, '3'),
    (0x18, '3'),
    (0x19, '3'),
    (0x1A, '3'),
    (0x1B, '3'),
    (0x1C, '3'),
    (0x1D, '3'),
    (0x1E, '3'),
    (0x1F, '3'),
    (0x20, '3'),
    (0x21, '3'),
    (0x22, '3'),
    (0x23, '3'),
    (0x24, '3'),
    (0x25, '3'),
    (0x26, '3'),
    (0x27, '3'),
    (0x28, '3'),
    (0x29, '3'),
    (0x2A, '3'),
    (0x2B, '3'),
    (0x2C, '3'),
    (0x2D, 'V'),
    (0x2E, 'V'),
    (0x2F, '3'),
    (0x30, 'V'),
    (0x31, 'V'),
    (0x32, 'V'),
    (0x33, 'V'),
    (0x34, 'V'),
    (0x35, 'V'),
    (0x36, 'V'),
    (0x37, 'V'),
    (0x38, 'V'),
    (0x39, 'V'),
    (0x3A, '3'),
    (0x3B, '3'),
    (0x3C, '3'),
    (0x3D, '3'),
    (0x3E, '3'),
    (0x3F, '3'),
    (0x40, '3'),
    (0x41, 'M', 'a'),
    (0x42, 'M', 'b'),
    (0x43, 'M', 'c'),
    (0x44, 'M', 'd'),
    (0x45, 'M', 'e'),
    (0x46, 'M', 'f'),
    (0x47, 'M', 'g'),
    (0x48, 'M', 'h'),
    (0x49, 'M', 'i'),
    (0x4A, 'M', 'j'),
    (0x4B, 'M', 'k'),
    (0x4C, 'M', 'l'),
    (0x4D, 'M', 'm'),
    (0x4E, 'M', 'n'),
    (0x4F, 'M', 'o'),
    (0x50, 'M', 'p'),
    (0x51, 'M', 'q'),
    (0x52, 'M', 'r'),
    (0x53, 'M', 's'),
    (0x54, 'M', 't'),
    (0x55, 'M', 'u'),
    (0x56, 'M', 'v'),
    (0x57, 'M', 'w'),
    (0x58, 'M', 'x'),
    (0x59, 'M', 'y'),
    (0x5A, 'M', 'z'),
    (0x5B, '3'),
    (0x5C, '3'),
    (0x5D, '3'),
    (0x5E, '3'),
    (0x5F, '3'),
    (0x60, '3'),
    (0x61, 'V'),
    (0x62, 'V'),
    (0x63, 'V'),
    ]

def _seg_1() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x64, 'V'),
    (0x65, 'V'),
    (0x66, 'V'),
    (0x67, 'V'),
    (0x68, 'V'),
    (0x69, 'V'),
    (0x6A, 'V'),
    (0x6B, 'V'),
    (0x6C, 'V'),
    (0x6D, 'V'),
    (0x6E, 'V'),
    (0x6F, 'V'),
    (0x70, 'V'),
    (0x71, 'V'),
    (0x72, 'V'),
    (0x73, 'V'),
    (0x74, 'V'),
    (0x75, 'V'),
    (0x76, 'V'),
    (0x77, 'V'),
    (0x78, 'V'),
    (0x79, 'V'),
    (0x7A, 'V'),
    (0x7B, '3'),
    (0x7C, '3'),
    (0x7D, '3'),
    (0x7E, '3'),
    (0x7F, '3'),
    (0x80, 'X'),
    (0x81, 'X'),
    (0x82, 'X'),
    (0x83, 'X'),
    (0x84, 'X'),
    (0x85, 'X'),
    (0x86, 'X'),
    (0x87, 'X'),
    (0x88, 'X'),
    (0x89, 'X'),
    (0x8A, 'X'),
    (0x8B, 'X'),
    (0x8C, 'X'),
    (0x8D, 'X'),
    (0x8E, 'X'),
    (0x8F, 'X'),
    (0x90, 'X'),
    (0x91, 'X'),
    (0x92, 'X'),
    (0x93, 'X'),
    (0x94, 'X'),
    (0x95, 'X'),
    (0x96, 'X'),
    (0x97, 'X'),
    (0x98, 'X'),
    (0x99, 'X'),
    (0x9A, 'X'),
    (0x9B, 'X'),
    (0x9C, 'X'),
    (0x9D, 'X'),
    (0x9E, 'X'),
    (0x9F, 'X'),
    (0xA0, '3', ' '),
    (0xA1, 'V'),
    (0xA2, 'V'),
    (0xA3, 'V'),
    (0xA4, 'V'),
    (0xA5, 'V'),
    (0xA6, 'V'),
    (0xA7, 'V'),
    (0xA8, '3', ' ̈'),
    (0xA9, 'V'),
    (0xAA, 'M', 'a'),
    (0xAB, 'V'),
    (0xAC, 'V'),
    (0xAD, 'I'),
    (0xAE, 'V'),
    (0xAF, '3', ' ̄'),
    (0xB0, 'V'),
    (0xB1, 'V'),
    (0xB2, 'M', '2'),
    (0xB3, 'M', '3'),
    (0xB4, '3', ' ́'),
    (0xB5, 'M', 'μ'),
    (0xB6, 'V'),
    (0xB7, 'V'),
    (0xB8, '3', ' ̧'),
    (0xB9, 'M', '1'),
    (0xBA, 'M', 'o'),
    (0xBB, 'V'),
    (0xBC, 'M', '1⁄4'),
    (0xBD, 'M', '1⁄2'),
    (0xBE, 'M', '3⁄4'),
    (0xBF, 'V'),
    (0xC0, 'M', 'à'),
    (0xC1, 'M', 'á'),
    (0xC2, 'M', 'â'),
    (0xC3, 'M', 'ã'),
    (0xC4, 'M', 'ä'),
    (0xC5, 'M', 'å'),
    (0xC6, 'M', 'æ'),
    (0xC7, 'M', 'ç'),
    ]

def _seg_2() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xC8, 'M', 'è'),
    (0xC9, 'M', 'é'),
    (0xCA, 'M', 'ê'),
    (0xCB, 'M', 'ë'),
    (0xCC, 'M', 'ì'),
    (0xCD, 'M', 'í'),
    (0xCE, 'M', 'î'),
    (0xCF, 'M', 'ï'),
    (0xD0, 'M', 'ð'),
    (0xD1, 'M', 'ñ'),
    (0xD2, 'M', 'ò'),
    (0xD3, 'M', 'ó'),
    (0xD4, 'M', 'ô'),
    (0xD5, 'M', 'õ'),
    (0xD6, 'M', 'ö'),
    (0xD7, 'V'),
    (0xD8, 'M', 'ø'),
    (0xD9, 'M', 'ù'),
    (0xDA, 'M', 'ú'),
    (0xDB, 'M', 'û'),
    (0xDC, 'M', 'ü'),
    (0xDD, 'M', 'ý'),
    (0xDE, 'M', 'þ'),
    (0xDF, 'D', 'ss'),
    (0xE0, 'V'),
    (0xE1, 'V'),
    (0xE2, 'V'),
    (0xE3, 'V'),
    (0xE4, 'V'),
    (0xE5, 'V'),
    (0xE6, 'V'),
    (0xE7, 'V'),
    (0xE8, 'V'),
    (0xE9, 'V'),
    (0xEA, 'V'),
    (0xEB, 'V'),
    (0xEC, 'V'),
    (0xED, 'V'),
    (0xEE, 'V'),
    (0xEF, 'V'),
    (0xF0, 'V'),
    (0xF1, 'V'),
    (0xF2, 'V'),
    (0xF3, 'V'),
    (0xF4, 'V'),
    (0xF5, 'V'),
    (0xF6, 'V'),
    (0xF7, 'V'),
    (0xF8, 'V'),
    (0xF9, 'V'),
    (0xFA, 'V'),
    (0xFB, 'V'),
    (0xFC, 'V'),
    (0xFD, 'V'),
    (0xFE, 'V'),
    (0xFF, 'V'),
    (0x100, 'M', 'ā'),
    (0x101, 'V'),
    (0x102, 'M', 'ă'),
    (0x103, 'V'),
    (0x104, 'M', 'ą'),
    (0x105, 'V'),
    (0x106, 'M', 'ć'),
    (0x107, 'V'),
    (0x108, 'M', 'ĉ'),
    (0x109, 'V'),
    (0x10A, 'M', 'ċ'),
    (0x10B, 'V'),
    (0x10C, 'M', 'č'),
    (0x10D, 'V'),
    (0x10E, 'M', 'ď'),
    (0x10F, 'V'),
    (0x110, 'M', 'đ'),
    (0x111, 'V'),
    (0x112, 'M', 'ē'),
    (0x113, 'V'),
    (0x114, 'M', 'ĕ'),
    (0x115, 'V'),
    (0x116, 'M', 'ė'),
    (0x117, 'V'),
    (0x118, 'M', 'ę'),
    (0x119, 'V'),
    (0x11A, 'M', 'ě'),
    (0x11B, 'V'),
    (0x11C, 'M', 'ĝ'),
    (0x11D, 'V'),
    (0x11E, 'M', 'ğ'),
    (0x11F, 'V'),
    (0x120, 'M', 'ġ'),
    (0x121, 'V'),
    (0x122, 'M', 'ģ'),
    (0x123, 'V'),
    (0x124, 'M', 'ĥ'),
    (0x125, 'V'),
    (0x126, 'M', 'ħ'),
    (0x127, 'V'),
    (0x128, 'M', 'ĩ'),
    (0x129, 'V'),
    (0x12A, 'M', 'ī'),
    (0x12B, 'V'),
    ]

def _seg_3() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x12C, 'M', 'ĭ'),
    (0x12D, 'V'),
    (0x12E, 'M', 'į'),
    (0x12F, 'V'),
    (0x130, 'M', 'i̇'),
    (0x131, 'V'),
    (0x132, 'M', 'ij'),
    (0x134, 'M', 'ĵ'),
    (0x135, 'V'),
    (0x136, 'M', 'ķ'),
    (0x137, 'V'),
    (0x139, 'M', 'ĺ'),
    (0x13A, 'V'),
    (0x13B, 'M', 'ļ'),
    (0x13C, 'V'),
    (0x13D, 'M', 'ľ'),
    (0x13E, 'V'),
    (0x13F, 'M', 'l·'),
    (0x141, 'M', 'ł'),
    (0x142, 'V'),
    (0x143, 'M', 'ń'),
    (0x144, 'V'),
    (0x145, 'M', 'ņ'),
    (0x146, 'V'),
    (0x147, 'M', 'ň'),
    (0x148, 'V'),
    (0x149, 'M', 'ʼn'),
    (0x14A, 'M', 'ŋ'),
    (0x14B, 'V'),
    (0x14C, 'M', 'ō'),
    (0x14D, 'V'),
    (0x14E, 'M', 'ŏ'),
    (0x14F, 'V'),
    (0x150, 'M', 'ő'),
    (0x151, 'V'),
    (0x152, 'M', 'œ'),
    (0x153, 'V'),
    (0x154, 'M', 'ŕ'),
    (0x155, 'V'),
    (0x156, 'M', 'ŗ'),
    (0x157, 'V'),
    (0x158, 'M', 'ř'),
    (0x159, 'V'),
    (0x15A, 'M', 'ś'),
    (0x15B, 'V'),
    (0x15C, 'M', 'ŝ'),
    (0x15D, 'V'),
    (0x15E, 'M', 'ş'),
    (0x15F, 'V'),
    (0x160, 'M', 'š'),
    (0x161, 'V'),
    (0x162, 'M', 'ţ'),
    (0x163, 'V'),
    (0x164, 'M', 'ť'),
    (0x165, 'V'),
    (0x166, 'M', 'ŧ'),
    (0x167, 'V'),
    (0x168, 'M', 'ũ'),
    (0x169, 'V'),
    (0x16A, 'M', 'ū'),
    (0x16B, 'V'),
    (0x16C, 'M', 'ŭ'),
    (0x16D, 'V'),
    (0x16E, 'M', 'ů'),
    (0x16F, 'V'),
    (0x170, 'M', 'ű'),
    (0x171, 'V'),
    (0x172, 'M', 'ų'),
    (0x173, 'V'),
    (0x174, 'M', 'ŵ'),
    (0x175, 'V'),
    (0x176, 'M', 'ŷ'),
    (0x177, 'V'),
    (0x178, 'M', 'ÿ'),
    (0x179, 'M', 'ź'),
    (0x17A, 'V'),
    (0x17B, 'M', 'ż'),
    (0x17C, 'V'),
    (0x17D, 'M', 'ž'),
    (0x17E, 'V'),
    (0x17F, 'M', 's'),
    (0x180, 'V'),
    (0x181, 'M', 'ɓ'),
    (0x182, 'M', 'ƃ'),
    (0x183, 'V'),
    (0x184, 'M', 'ƅ'),
    (0x185, 'V'),
    (0x186, 'M', 'ɔ'),
    (0x187, 'M', 'ƈ'),
    (0x188, 'V'),
    (0x189, 'M', 'ɖ'),
    (0x18A, 'M', 'ɗ'),
    (0x18B, 'M', 'ƌ'),
    (0x18C, 'V'),
    (0x18E, 'M', 'ǝ'),
    (0x18F, 'M', 'ə'),
    (0x190, 'M', 'ɛ'),
    (0x191, 'M', 'ƒ'),
    (0x192, 'V'),
    (0x193, 'M', 'ɠ'),
    ]

def _seg_4() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x194, 'M', 'ɣ'),
    (0x195, 'V'),
    (0x196, 'M', 'ɩ'),
    (0x197, 'M', 'ɨ'),
    (0x198, 'M', 'ƙ'),
    (0x199, 'V'),
    (0x19C, 'M', 'ɯ'),
    (0x19D, 'M', 'ɲ'),
    (0x19E, 'V'),
    (0x19F, 'M', 'ɵ'),
    (0x1A0, 'M', 'ơ'),
    (0x1A1, 'V'),
    (0x1A2, 'M', 'ƣ'),
    (0x1A3, 'V'),
    (0x1A4, 'M', 'ƥ'),
    (0x1A5, 'V'),
    (0x1A6, 'M', 'ʀ'),
    (0x1A7, 'M', 'ƨ'),
    (0x1A8, 'V'),
    (0x1A9, 'M', 'ʃ'),
    (0x1AA, 'V'),
    (0x1AC, 'M', 'ƭ'),
    (0x1AD, 'V'),
    (0x1AE, 'M', 'ʈ'),
    (0x1AF, 'M', 'ư'),
    (0x1B0, 'V'),
    (0x1B1, 'M', 'ʊ'),
    (0x1B2, 'M', 'ʋ'),
    (0x1B3, 'M', 'ƴ'),
    (0x1B4, 'V'),
    (0x1B5, 'M', 'ƶ'),
    (0x1B6, 'V'),
    (0x1B7, 'M', 'ʒ'),
    (0x1B8, 'M', 'ƹ'),
    (0x1B9, 'V'),
    (0x1BC, 'M', 'ƽ'),
    (0x1BD, 'V'),
    (0x1C4, 'M', 'dž'),
    (0x1C7, 'M', 'lj'),
    (0x1CA, 'M', 'nj'),
    (0x1CD, 'M', 'ǎ'),
    (0x1CE, 'V'),
    (0x1CF, 'M', 'ǐ'),
    (0x1D0, 'V'),
    (0x1D1, 'M', 'ǒ'),
    (0x1D2, 'V'),
    (0x1D3, 'M', 'ǔ'),
    (0x1D4, 'V'),
    (0x1D5, 'M', 'ǖ'),
    (0x1D6, 'V'),
    (0x1D7, 'M', 'ǘ'),
    (0x1D8, 'V'),
    (0x1D9, 'M', 'ǚ'),
    (0x1DA, 'V'),
    (0x1DB, 'M', 'ǜ'),
    (0x1DC, 'V'),
    (0x1DE, 'M', 'ǟ'),
    (0x1DF, 'V'),
    (0x1E0, 'M', 'ǡ'),
    (0x1E1, 'V'),
    (0x1E2, 'M', 'ǣ'),
    (0x1E3, 'V'),
    (0x1E4, 'M', 'ǥ'),
    (0x1E5, 'V'),
    (0x1E6, 'M', 'ǧ'),
    (0x1E7, 'V'),
    (0x1E8, 'M', 'ǩ'),
    (0x1E9, 'V'),
    (0x1EA, 'M', 'ǫ'),
    (0x1EB, 'V'),
    (0x1EC, 'M', 'ǭ'),
    (0x1ED, 'V'),
    (0x1EE, 'M', 'ǯ'),
    (0x1EF, 'V'),
    (0x1F1, 'M', 'dz'),
    (0x1F4, 'M', 'ǵ'),
    (0x1F5, 'V'),
    (0x1F6, 'M', 'ƕ'),
    (0x1F7, 'M', 'ƿ'),
    (0x1F8, 'M', 'ǹ'),
    (0x1F9, 'V'),
    (0x1FA, 'M', 'ǻ'),
    (0x1FB, 'V'),
    (0x1FC, 'M', 'ǽ'),
    (0x1FD, 'V'),
    (0x1FE, 'M', 'ǿ'),
    (0x1FF, 'V'),
    (0x200, 'M', 'ȁ'),
    (0x201, 'V'),
    (0x202, 'M', 'ȃ'),
    (0x203, 'V'),
    (0x204, 'M', 'ȅ'),
    (0x205, 'V'),
    (0x206, 'M', 'ȇ'),
    (0x207, 'V'),
    (0x208, 'M', 'ȉ'),
    (0x209, 'V'),
    (0x20A, 'M', 'ȋ'),
    (0x20B, 'V'),
    (0x20C, 'M', 'ȍ'),
    ]

def _seg_5() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x20D, 'V'),
    (0x20E, 'M', 'ȏ'),
    (0x20F, 'V'),
    (0x210, 'M', 'ȑ'),
    (0x211, 'V'),
    (0x212, 'M', 'ȓ'),
    (0x213, 'V'),
    (0x214, 'M', 'ȕ'),
    (0x215, 'V'),
    (0x216, 'M', 'ȗ'),
    (0x217, 'V'),
    (0x218, 'M', 'ș'),
    (0x219, 'V'),
    (0x21A, 'M', 'ț'),
    (0x21B, 'V'),
    (0x21C, 'M', 'ȝ'),
    (0x21D, 'V'),
    (0x21E, 'M', 'ȟ'),
    (0x21F, 'V'),
    (0x220, 'M', 'ƞ'),
    (0x221, 'V'),
    (0x222, 'M', 'ȣ'),
    (0x223, 'V'),
    (0x224, 'M', 'ȥ'),
    (0x225, 'V'),
    (0x226, 'M', 'ȧ'),
    (0x227, 'V'),
    (0x228, 'M', 'ȩ'),
    (0x229, 'V'),
    (0x22A, 'M', 'ȫ'),
    (0x22B, 'V'),
    (0x22C, 'M', 'ȭ'),
    (0x22D, 'V'),
    (0x22E, 'M', 'ȯ'),
    (0x22F, 'V'),
    (0x230, 'M', 'ȱ'),
    (0x231, 'V'),
    (0x232, 'M', 'ȳ'),
    (0x233, 'V'),
    (0x23A, 'M', 'ⱥ'),
    (0x23B, 'M', 'ȼ'),
    (0x23C, 'V'),
    (0x23D, 'M', 'ƚ'),
    (0x23E, 'M', 'ⱦ'),
    (0x23F, 'V'),
    (0x241, 'M', 'ɂ'),
    (0x242, 'V'),
    (0x243, 'M', 'ƀ'),
    (0x244, 'M', 'ʉ'),
    (0x245, 'M', 'ʌ'),
    (0x246, 'M', 'ɇ'),
    (0x247, 'V'),
    (0x248, 'M', 'ɉ'),
    (0x249, 'V'),
    (0x24A, 'M', 'ɋ'),
    (0x24B, 'V'),
    (0x24C, 'M', 'ɍ'),
    (0x24D, 'V'),
    (0x24E, 'M', 'ɏ'),
    (0x24F, 'V'),
    (0x2B0, 'M', 'h'),
    (0x2B1, 'M', 'ɦ'),
    (0x2B2, 'M', 'j'),
    (0x2B3, 'M', 'r'),
    (0x2B4, 'M', 'ɹ'),
    (0x2B5, 'M', 'ɻ'),
    (0x2B6, 'M', 'ʁ'),
    (0x2B7, 'M', 'w'),
    (0x2B8, 'M', 'y'),
    (0x2B9, 'V'),
    (0x2D8, '3', ' ̆'),
    (0x2D9, '3', ' ̇'),
    (0x2DA, '3', ' ̊'),
    (0x2DB, '3', ' ̨'),
    (0x2DC, '3', ' ̃'),
    (0x2DD, '3', ' ̋'),
    (0x2DE, 'V'),
    (0x2E0, 'M', 'ɣ'),
    (0x2E1, 'M', 'l'),
    (0x2E2, 'M', 's'),
    (0x2E3, 'M', 'x'),
    (0x2E4, 'M', 'ʕ'),
    (0x2E5, 'V'),
    (0x340, 'M', '̀'),
    (0x341, 'M', '́'),
    (0x342, 'V'),
    (0x343, 'M', '̓'),
    (0x344, 'M', '̈́'),
    (0x345, 'M', 'ι'),
    (0x346, 'V'),
    (0x34F, 'I'),
    (0x350, 'V'),
    (0x370, 'M', 'ͱ'),
    (0x371, 'V'),
    (0x372, 'M', 'ͳ'),
    (0x373, 'V'),
    (0x374, 'M', 'ʹ'),
    (0x375, 'V'),
    (0x376, 'M', 'ͷ'),
    (0x377, 'V'),
    ]

def _seg_6() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x378, 'X'),
    (0x37A, '3', ' ι'),
    (0x37B, 'V'),
    (0x37E, '3', ';'),
    (0x37F, 'M', 'ϳ'),
    (0x380, 'X'),
    (0x384, '3', ' ́'),
    (0x385, '3', ' ̈́'),
    (0x386, 'M', 'ά'),
    (0x387, 'M', '·'),
    (0x388, 'M', 'έ'),
    (0x389, 'M', 'ή'),
    (0x38A, 'M', 'ί'),
    (0x38B, 'X'),
    (0x38C, 'M', 'ό'),
    (0x38D, 'X'),
    (0x38E, 'M', 'ύ'),
    (0x38F, 'M', 'ώ'),
    (0x390, 'V'),
    (0x391, 'M', 'α'),
    (0x392, 'M', 'β'),
    (0x393, 'M', 'γ'),
    (0x394, 'M', 'δ'),
    (0x395, 'M', 'ε'),
    (0x396, 'M', 'ζ'),
    (0x397, 'M', 'η'),
    (0x398, 'M', 'θ'),
    (0x399, 'M', 'ι'),
    (0x39A, 'M', 'κ'),
    (0x39B, 'M', 'λ'),
    (0x39C, 'M', 'μ'),
    (0x39D, 'M', 'ν'),
    (0x39E, 'M', 'ξ'),
    (0x39F, 'M', 'ο'),
    (0x3A0, 'M', 'π'),
    (0x3A1, 'M', 'ρ'),
    (0x3A2, 'X'),
    (0x3A3, 'M', 'σ'),
    (0x3A4, 'M', 'τ'),
    (0x3A5, 'M', 'υ'),
    (0x3A6, 'M', 'φ'),
    (0x3A7, 'M', 'χ'),
    (0x3A8, 'M', 'ψ'),
    (0x3A9, 'M', 'ω'),
    (0x3AA, 'M', 'ϊ'),
    (0x3AB, 'M', 'ϋ'),
    (0x3AC, 'V'),
    (0x3C2, 'D', 'σ'),
    (0x3C3, 'V'),
    (0x3CF, 'M', 'ϗ'),
    (0x3D0, 'M', 'β'),
    (0x3D1, 'M', 'θ'),
    (0x3D2, 'M', 'υ'),
    (0x3D3, 'M', 'ύ'),
    (0x3D4, 'M', 'ϋ'),
    (0x3D5, 'M', 'φ'),
    (0x3D6, 'M', 'π'),
    (0x3D7, 'V'),
    (0x3D8, 'M', 'ϙ'),
    (0x3D9, 'V'),
    (0x3DA, 'M', 'ϛ'),
    (0x3DB, 'V'),
    (0x3DC, 'M', 'ϝ'),
    (0x3DD, 'V'),
    (0x3DE, 'M', 'ϟ'),
    (0x3DF, 'V'),
    (0x3E0, 'M', 'ϡ'),
    (0x3E1, 'V'),
    (0x3E2, 'M', 'ϣ'),
    (0x3E3, 'V'),
    (0x3E4, 'M', 'ϥ'),
    (0x3E5, 'V'),
    (0x3E6, 'M', 'ϧ'),
    (0x3E7, 'V'),
    (0x3E8, 'M', 'ϩ'),
    (0x3E9, 'V'),
    (0x3EA, 'M', 'ϫ'),
    (0x3EB, 'V'),
    (0x3EC, 'M', 'ϭ'),
    (0x3ED, 'V'),
    (0x3EE, 'M', 'ϯ'),
    (0x3EF, 'V'),
    (0x3F0, 'M', 'κ'),
    (0x3F1, 'M', 'ρ'),
    (0x3F2, 'M', 'σ'),
    (0x3F3, 'V'),
    (0x3F4, 'M', 'θ'),
    (0x3F5, 'M', 'ε'),
    (0x3F6, 'V'),
    (0x3F7, 'M', 'ϸ'),
    (0x3F8, 'V'),
    (0x3F9, 'M', 'σ'),
    (0x3FA, 'M', 'ϻ'),
    (0x3FB, 'V'),
    (0x3FD, 'M', 'ͻ'),
    (0x3FE, 'M', 'ͼ'),
    (0x3FF, 'M', 'ͽ'),
    (0x400, 'M', 'ѐ'),
    (0x401, 'M', 'ё'),
    (0x402, 'M', 'ђ'),
    ]

def _seg_7() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x403, 'M', 'ѓ'),
    (0x404, 'M', 'є'),
    (0x405, 'M', 'ѕ'),
    (0x406, 'M', 'і'),
    (0x407, 'M', 'ї'),
    (0x408, 'M', 'ј'),
    (0x409, 'M', 'љ'),
    (0x40A, 'M', 'њ'),
    (0x40B, 'M', 'ћ'),
    (0x40C, 'M', 'ќ'),
    (0x40D, 'M', 'ѝ'),
    (0x40E, 'M', 'ў'),
    (0x40F, 'M', 'џ'),
    (0x410, 'M', 'а'),
    (0x411, 'M', 'б'),
    (0x412, 'M', 'в'),
    (0x413, 'M', 'г'),
    (0x414, 'M', 'д'),
    (0x415, 'M', 'е'),
    (0x416, 'M', 'ж'),
    (0x417, 'M', 'з'),
    (0x418, 'M', 'и'),
    (0x419, 'M', 'й'),
    (0x41A, 'M', 'к'),
    (0x41B, 'M', 'л'),
    (0x41C, 'M', 'м'),
    (0x41D, 'M', 'н'),
    (0x41E, 'M', 'о'),
    (0x41F, 'M', 'п'),
    (0x420, 'M', 'р'),
    (0x421, 'M', 'с'),
    (0x422, 'M', 'т'),
    (0x423, 'M', 'у'),
    (0x424, 'M', 'ф'),
    (0x425, 'M', 'х'),
    (0x426, 'M', 'ц'),
    (0x427, 'M', 'ч'),
    (0x428, 'M', 'ш'),
    (0x429, 'M', 'щ'),
    (0x42A, 'M', 'ъ'),
    (0x42B, 'M', 'ы'),
    (0x42C, 'M', 'ь'),
    (0x42D, 'M', 'э'),
    (0x42E, 'M', 'ю'),
    (0x42F, 'M', 'я'),
    (0x430, 'V'),
    (0x460, 'M', 'ѡ'),
    (0x461, 'V'),
    (0x462, 'M', 'ѣ'),
    (0x463, 'V'),
    (0x464, 'M', 'ѥ'),
    (0x465, 'V'),
    (0x466, 'M', 'ѧ'),
    (0x467, 'V'),
    (0x468, 'M', 'ѩ'),
    (0x469, 'V'),
    (0x46A, 'M', 'ѫ'),
    (0x46B, 'V'),
    (0x46C, 'M', 'ѭ'),
    (0x46D, 'V'),
    (0x46E, 'M', 'ѯ'),
    (0x46F, 'V'),
    (0x470, 'M', 'ѱ'),
    (0x471, 'V'),
    (0x472, 'M', 'ѳ'),
    (0x473, 'V'),
    (0x474, 'M', 'ѵ'),
    (0x475, 'V'),
    (0x476, 'M', 'ѷ'),
    (0x477, 'V'),
    (0x478, 'M', 'ѹ'),
    (0x479, 'V'),
    (0x47A, 'M', 'ѻ'),
    (0x47B, 'V'),
    (0x47C, 'M', 'ѽ'),
    (0x47D, 'V'),
    (0x47E, 'M', 'ѿ'),
    (0x47F, 'V'),
    (0x480, 'M', 'ҁ'),
    (0x481, 'V'),
    (0x48A, 'M', 'ҋ'),
    (0x48B, 'V'),
    (0x48C, 'M', 'ҍ'),
    (0x48D, 'V'),
    (0x48E, 'M', 'ҏ'),
    (0x48F, 'V'),
    (0x490, 'M', 'ґ'),
    (0x491, 'V'),
    (0x492, 'M', 'ғ'),
    (0x493, 'V'),
    (0x494, 'M', 'ҕ'),
    (0x495, 'V'),
    (0x496, 'M', 'җ'),
    (0x497, 'V'),
    (0x498, 'M', 'ҙ'),
    (0x499, 'V'),
    (0x49A, 'M', 'қ'),
    (0x49B, 'V'),
    (0x49C, 'M', 'ҝ'),
    (0x49D, 'V'),
    ]

def _seg_8() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x49E, 'M', 'ҟ'),
    (0x49F, 'V'),
    (0x4A0, 'M', 'ҡ'),
    (0x4A1, 'V'),
    (0x4A2, 'M', 'ң'),
    (0x4A3, 'V'),
    (0x4A4, 'M', 'ҥ'),
    (0x4A5, 'V'),
    (0x4A6, 'M', 'ҧ'),
    (0x4A7, 'V'),
    (0x4A8, 'M', 'ҩ'),
    (0x4A9, 'V'),
    (0x4AA, 'M', 'ҫ'),
    (0x4AB, 'V'),
    (0x4AC, 'M', 'ҭ'),
    (0x4AD, 'V'),
    (0x4AE, 'M', 'ү'),
    (0x4AF, 'V'),
    (0x4B0, 'M', 'ұ'),
    (0x4B1, 'V'),
    (0x4B2, 'M', 'ҳ'),
    (0x4B3, 'V'),
    (0x4B4, 'M', 'ҵ'),
    (0x4B5, 'V'),
    (0x4B6, 'M', 'ҷ'),
    (0x4B7, 'V'),
    (0x4B8, 'M', 'ҹ'),
    (0x4B9, 'V'),
    (0x4BA, 'M', 'һ'),
    (0x4BB, 'V'),
    (0x4BC, 'M', 'ҽ'),
    (0x4BD, 'V'),
    (0x4BE, 'M', 'ҿ'),
    (0x4BF, 'V'),
    (0x4C0, 'X'),
    (0x4C1, 'M', 'ӂ'),
    (0x4C2, 'V'),
    (0x4C3, 'M', 'ӄ'),
    (0x4C4, 'V'),
    (0x4C5, 'M', 'ӆ'),
    (0x4C6, 'V'),
    (0x4C7, 'M', 'ӈ'),
    (0x4C8, 'V'),
    (0x4C9, 'M', 'ӊ'),
    (0x4CA, 'V'),
    (0x4CB, 'M', 'ӌ'),
    (0x4CC, 'V'),
    (0x4CD, 'M', 'ӎ'),
    (0x4CE, 'V'),
    (0x4D0, 'M', 'ӑ'),
    (0x4D1, 'V'),
    (0x4D2, 'M', 'ӓ'),
    (0x4D3, 'V'),
    (0x4D4, 'M', 'ӕ'),
    (0x4D5, 'V'),
    (0x4D6, 'M', 'ӗ'),
    (0x4D7, 'V'),
    (0x4D8, 'M', 'ә'),
    (0x4D9, 'V'),
    (0x4DA, 'M', 'ӛ'),
    (0x4DB, 'V'),
    (0x4DC, 'M', 'ӝ'),
    (0x4DD, 'V'),
    (0x4DE, 'M', 'ӟ'),
    (0x4DF, 'V'),
    (0x4E0, 'M', 'ӡ'),
    (0x4E1, 'V'),
    (0x4E2, 'M', 'ӣ'),
    (0x4E3, 'V'),
    (0x4E4, 'M', 'ӥ'),
    (0x4E5, 'V'),
    (0x4E6, 'M', 'ӧ'),
    (0x4E7, 'V'),
    (0x4E8, 'M', 'ө'),
    (0x4E9, 'V'),
    (0x4EA, 'M', 'ӫ'),
    (0x4EB, 'V'),
    (0x4EC, 'M', 'ӭ'),
    (0x4ED, 'V'),
    (0x4EE, 'M', 'ӯ'),
    (0x4EF, 'V'),
    (0x4F0, 'M', 'ӱ'),
    (0x4F1, 'V'),
    (0x4F2, 'M', 'ӳ'),
    (0x4F3, 'V'),
    (0x4F4, 'M', 'ӵ'),
    (0x4F5, 'V'),
    (0x4F6, 'M', 'ӷ'),
    (0x4F7, 'V'),
    (0x4F8, 'M', 'ӹ'),
    (0x4F9, 'V'),
    (0x4FA, 'M', 'ӻ'),
    (0x4FB, 'V'),
    (0x4FC, 'M', 'ӽ'),
    (0x4FD, 'V'),
    (0x4FE, 'M', 'ӿ'),
    (0x4FF, 'V'),
    (0x500, 'M', 'ԁ'),
    (0x501, 'V'),
    (0x502, 'M', 'ԃ'),
    ]

def _seg_9() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x503, 'V'),
    (0x504, 'M', 'ԅ'),
    (0x505, 'V'),
    (0x506, 'M', 'ԇ'),
    (0x507, 'V'),
    (0x508, 'M', 'ԉ'),
    (0x509, 'V'),
    (0x50A, 'M', 'ԋ'),
    (0x50B, 'V'),
    (0x50C, 'M', 'ԍ'),
    (0x50D, 'V'),
    (0x50E, 'M', 'ԏ'),
    (0x50F, 'V'),
    (0x510, 'M', 'ԑ'),
    (0x511, 'V'),
    (0x512, 'M', 'ԓ'),
    (0x513, 'V'),
    (0x514, 'M', 'ԕ'),
    (0x515, 'V'),
    (0x516, 'M', 'ԗ'),
    (0x517, 'V'),
    (0x518, 'M', 'ԙ'),
    (0x519, 'V'),
    (0x51A, 'M', 'ԛ'),
    (0x51B, 'V'),
    (0x51C, 'M', 'ԝ'),
    (0x51D, 'V'),
    (0x51E, 'M', 'ԟ'),
    (0x51F, 'V'),
    (0x520, 'M', 'ԡ'),
    (0x521, 'V'),
    (0x522, 'M', 'ԣ'),
    (0x523, 'V'),
    (0x524, 'M', 'ԥ'),
    (0x525, 'V'),
    (0x526, 'M', 'ԧ'),
    (0x527, 'V'),
    (0x528, 'M', 'ԩ'),
    (0x529, 'V'),
    (0x52A, 'M', 'ԫ'),
    (0x52B, 'V'),
    (0x52C, 'M', 'ԭ'),
    (0x52D, 'V'),
    (0x52E, 'M', 'ԯ'),
    (0x52F, 'V'),
    (0x530, 'X'),
    (0x531, 'M', 'ա'),
    (0x532, 'M', 'բ'),
    (0x533, 'M', 'գ'),
    (0x534, 'M', 'դ'),
    (0x535, 'M', 'ե'),
    (0x536, 'M', 'զ'),
    (0x537, 'M', 'է'),
    (0x538, 'M', 'ը'),
    (0x539, 'M', 'թ'),
    (0x53A, 'M', 'ժ'),
    (0x53B, 'M', 'ի'),
    (0x53C, 'M', 'լ'),
    (0x53D, 'M', 'խ'),
    (0x53E, 'M', 'ծ'),
    (0x53F, 'M', 'կ'),
    (0x540, 'M', 'հ'),
    (0x541, 'M', 'ձ'),
    (0x542, 'M', 'ղ'),
    (0x543, 'M', 'ճ'),
    (0x544, 'M', 'մ'),
    (0x545, 'M', 'յ'),
    (0x546, 'M', 'ն'),
    (0x547, 'M', 'շ'),
    (0x548, 'M', 'ո'),
    (0x549, 'M', 'չ'),
    (0x54A, 'M', 'պ'),
    (0x54B, 'M', 'ջ'),
    (0x54C, 'M', 'ռ'),
    (0x54D, 'M', 'ս'),
    (0x54E, 'M', 'վ'),
    (0x54F, 'M', 'տ'),
    (0x550, 'M', 'ր'),
    (0x551, 'M', 'ց'),
    (0x552, 'M', 'ւ'),
    (0x553, 'M', 'փ'),
    (0x554, 'M', 'ք'),
    (0x555, 'M', 'օ'),
    (0x556, 'M', 'ֆ'),
    (0x557, 'X'),
    (0x559, 'V'),
    (0x587, 'M', 'եւ'),
    (0x588, 'V'),
    (0x58B, 'X'),
    (0x58D, 'V'),
    (0x590, 'X'),
    (0x591, 'V'),
    (0x5C8, 'X'),
    (0x5D0, 'V'),
    (0x5EB, 'X'),
    (0x5EF, 'V'),
    (0x5F5, 'X'),
    (0x606, 'V'),
    (0x61C, 'X'),
    (0x61D, 'V'),
    ]

def _seg_10() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x675, 'M', 'اٴ'),
    (0x676, 'M', 'وٴ'),
    (0x677, 'M', 'ۇٴ'),
    (0x678, 'M', 'يٴ'),
    (0x679, 'V'),
    (0x6DD, 'X'),
    (0x6DE, 'V'),
    (0x70E, 'X'),
    (0x710, 'V'),
    (0x74B, 'X'),
    (0x74D, 'V'),
    (0x7B2, 'X'),
    (0x7C0, 'V'),
    (0x7FB, 'X'),
    (0x7FD, 'V'),
    (0x82E, 'X'),
    (0x830, 'V'),
    (0x83F, 'X'),
    (0x840, 'V'),
    (0x85C, 'X'),
    (0x85E, 'V'),
    (0x85F, 'X'),
    (0x860, 'V'),
    (0x86B, 'X'),
    (0x870, 'V'),
    (0x88F, 'X'),
    (0x898, 'V'),
    (0x8E2, 'X'),
    (0x8E3, 'V'),
    (0x958, 'M', 'क़'),
    (0x959, 'M', 'ख़'),
    (0x95A, 'M', 'ग़'),
    (0x95B, 'M', 'ज़'),
    (0x95C, 'M', 'ड़'),
    (0x95D, 'M', 'ढ़'),
    (0x95E, 'M', 'फ़'),
    (0x95F, 'M', 'य़'),
    (0x960, 'V'),
    (0x984, 'X'),
    (0x985, 'V'),
    (0x98D, 'X'),
    (0x98F, 'V'),
    (0x991, 'X'),
    (0x993, 'V'),
    (0x9A9, 'X'),
    (0x9AA, 'V'),
    (0x9B1, 'X'),
    (0x9B2, 'V'),
    (0x9B3, 'X'),
    (0x9B6, 'V'),
    (0x9BA, 'X'),
    (0x9BC, 'V'),
    (0x9C5, 'X'),
    (0x9C7, 'V'),
    (0x9C9, 'X'),
    (0x9CB, 'V'),
    (0x9CF, 'X'),
    (0x9D7, 'V'),
    (0x9D8, 'X'),
    (0x9DC, 'M', 'ড়'),
    (0x9DD, 'M', 'ঢ়'),
    (0x9DE, 'X'),
    (0x9DF, 'M', 'য়'),
    (0x9E0, 'V'),
    (0x9E4, 'X'),
    (0x9E6, 'V'),
    (0x9FF, 'X'),
    (0xA01, 'V'),
    (0xA04, 'X'),
    (0xA05, 'V'),
    (0xA0B, 'X'),
    (0xA0F, 'V'),
    (0xA11, 'X'),
    (0xA13, 'V'),
    (0xA29, 'X'),
    (0xA2A, 'V'),
    (0xA31, 'X'),
    (0xA32, 'V'),
    (0xA33, 'M', 'ਲ਼'),
    (0xA34, 'X'),
    (0xA35, 'V'),
    (0xA36, 'M', 'ਸ਼'),
    (0xA37, 'X'),
    (0xA38, 'V'),
    (0xA3A, 'X'),
    (0xA3C, 'V'),
    (0xA3D, 'X'),
    (0xA3E, 'V'),
    (0xA43, 'X'),
    (0xA47, 'V'),
    (0xA49, 'X'),
    (0xA4B, 'V'),
    (0xA4E, 'X'),
    (0xA51, 'V'),
    (0xA52, 'X'),
    (0xA59, 'M', 'ਖ਼'),
    (0xA5A, 'M', 'ਗ਼'),
    (0xA5B, 'M', 'ਜ਼'),
    (0xA5C, 'V'),
    (0xA5D, 'X'),
    ]

def _seg_11() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xA5E, 'M', 'ਫ਼'),
    (0xA5F, 'X'),
    (0xA66, 'V'),
    (0xA77, 'X'),
    (0xA81, 'V'),
    (0xA84, 'X'),
    (0xA85, 'V'),
    (0xA8E, 'X'),
    (0xA8F, 'V'),
    (0xA92, 'X'),
    (0xA93, 'V'),
    (0xAA9, 'X'),
    (0xAAA, 'V'),
    (0xAB1, 'X'),
    (0xAB2, 'V'),
    (0xAB4, 'X'),
    (0xAB5, 'V'),
    (0xABA, 'X'),
    (0xABC, 'V'),
    (0xAC6, 'X'),
    (0xAC7, 'V'),
    (0xACA, 'X'),
    (0xACB, 'V'),
    (0xACE, 'X'),
    (0xAD0, 'V'),
    (0xAD1, 'X'),
    (0xAE0, 'V'),
    (0xAE4, 'X'),
    (0xAE6, 'V'),
    (0xAF2, 'X'),
    (0xAF9, 'V'),
    (0xB00, 'X'),
    (0xB01, 'V'),
    (0xB04, 'X'),
    (0xB05, 'V'),
    (0xB0D, 'X'),
    (0xB0F, 'V'),
    (0xB11, 'X'),
    (0xB13, 'V'),
    (0xB29, 'X'),
    (0xB2A, 'V'),
    (0xB31, 'X'),
    (0xB32, 'V'),
    (0xB34, 'X'),
    (0xB35, 'V'),
    (0xB3A, 'X'),
    (0xB3C, 'V'),
    (0xB45, 'X'),
    (0xB47, 'V'),
    (0xB49, 'X'),
    (0xB4B, 'V'),
    (0xB4E, 'X'),
    (0xB55, 'V'),
    (0xB58, 'X'),
    (0xB5C, 'M', 'ଡ଼'),
    (0xB5D, 'M', 'ଢ଼'),
    (0xB5E, 'X'),
    (0xB5F, 'V'),
    (0xB64, 'X'),
    (0xB66, 'V'),
    (0xB78, 'X'),
    (0xB82, 'V'),
    (0xB84, 'X'),
    (0xB85, 'V'),
    (0xB8B, 'X'),
    (0xB8E, 'V'),
    (0xB91, 'X'),
    (0xB92, 'V'),
    (0xB96, 'X'),
    (0xB99, 'V'),
    (0xB9B, 'X'),
    (0xB9C, 'V'),
    (0xB9D, 'X'),
    (0xB9E, 'V'),
    (0xBA0, 'X'),
    (0xBA3, 'V'),
    (0xBA5, 'X'),
    (0xBA8, 'V'),
    (0xBAB, 'X'),
    (0xBAE, 'V'),
    (0xBBA, 'X'),
    (0xBBE, 'V'),
    (0xBC3, 'X'),
    (0xBC6, 'V'),
    (0xBC9, 'X'),
    (0xBCA, 'V'),
    (0xBCE, 'X'),
    (0xBD0, 'V'),
    (0xBD1, 'X'),
    (0xBD7, 'V'),
    (0xBD8, 'X'),
    (0xBE6, 'V'),
    (0xBFB, 'X'),
    (0xC00, 'V'),
    (0xC0D, 'X'),
    (0xC0E, 'V'),
    (0xC11, 'X'),
    (0xC12, 'V'),
    (0xC29, 'X'),
    (0xC2A, 'V'),
    ]

def _seg_12() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xC3A, 'X'),
    (0xC3C, 'V'),
    (0xC45, 'X'),
    (0xC46, 'V'),
    (0xC49, 'X'),
    (0xC4A, 'V'),
    (0xC4E, 'X'),
    (0xC55, 'V'),
    (0xC57, 'X'),
    (0xC58, 'V'),
    (0xC5B, 'X'),
    (0xC5D, 'V'),
    (0xC5E, 'X'),
    (0xC60, 'V'),
    (0xC64, 'X'),
    (0xC66, 'V'),
    (0xC70, 'X'),
    (0xC77, 'V'),
    (0xC8D, 'X'),
    (0xC8E, 'V'),
    (0xC91, 'X'),
    (0xC92, 'V'),
    (0xCA9, 'X'),
    (0xCAA, 'V'),
    (0xCB4, 'X'),
    (0xCB5, 'V'),
    (0xCBA, 'X'),
    (0xCBC, 'V'),
    (0xCC5, 'X'),
    (0xCC6, 'V'),
    (0xCC9, 'X'),
    (0xCCA, 'V'),
    (0xCCE, 'X'),
    (0xCD5, 'V'),
    (0xCD7, 'X'),
    (0xCDD, 'V'),
    (0xCDF, 'X'),
    (0xCE0, 'V'),
    (0xCE4, 'X'),
    (0xCE6, 'V'),
    (0xCF0, 'X'),
    (0xCF1, 'V'),
    (0xCF4, 'X'),
    (0xD00, 'V'),
    (0xD0D, 'X'),
    (0xD0E, 'V'),
    (0xD11, 'X'),
    (0xD12, 'V'),
    (0xD45, 'X'),
    (0xD46, 'V'),
    (0xD49, 'X'),
    (0xD4A, 'V'),
    (0xD50, 'X'),
    (0xD54, 'V'),
    (0xD64, 'X'),
    (0xD66, 'V'),
    (0xD80, 'X'),
    (0xD81, 'V'),
    (0xD84, 'X'),
    (0xD85, 'V'),
    (0xD97, 'X'),
    (0xD9A, 'V'),
    (0xDB2, 'X'),
    (0xDB3, 'V'),
    (0xDBC, 'X'),
    (0xDBD, 'V'),
    (0xDBE, 'X'),
    (0xDC0, 'V'),
    (0xDC7, 'X'),
    (0xDCA, 'V'),
    (0xDCB, 'X'),
    (0xDCF, 'V'),
    (0xDD5, 'X'),
    (0xDD6, 'V'),
    (0xDD7, 'X'),
    (0xDD8, 'V'),
    (0xDE0, 'X'),
    (0xDE6, 'V'),
    (0xDF0, 'X'),
    (0xDF2, 'V'),
    (0xDF5, 'X'),
    (0xE01, 'V'),
    (0xE33, 'M', 'ํา'),
    (0xE34, 'V'),
    (0xE3B, 'X'),
    (0xE3F, 'V'),
    (0xE5C, 'X'),
    (0xE81, 'V'),
    (0xE83, 'X'),
    (0xE84, 'V'),
    (0xE85, 'X'),
    (0xE86, 'V'),
    (0xE8B, 'X'),
    (0xE8C, 'V'),
    (0xEA4, 'X'),
    (0xEA5, 'V'),
    (0xEA6, 'X'),
    (0xEA7, 'V'),
    (0xEB3, 'M', 'ໍາ'),
    (0xEB4, 'V'),
    ]

def _seg_13() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xEBE, 'X'),
    (0xEC0, 'V'),
    (0xEC5, 'X'),
    (0xEC6, 'V'),
    (0xEC7, 'X'),
    (0xEC8, 'V'),
    (0xECF, 'X'),
    (0xED0, 'V'),
    (0xEDA, 'X'),
    (0xEDC, 'M', 'ຫນ'),
    (0xEDD, 'M', 'ຫມ'),
    (0xEDE, 'V'),
    (0xEE0, 'X'),
    (0xF00, 'V'),
    (0xF0C, 'M', '་'),
    (0xF0D, 'V'),
    (0xF43, 'M', 'གྷ'),
    (0xF44, 'V'),
    (0xF48, 'X'),
    (0xF49, 'V'),
    (0xF4D, 'M', 'ཌྷ'),
    (0xF4E, 'V'),
    (0xF52, 'M', 'དྷ'),
    (0xF53, 'V'),
    (0xF57, 'M', 'བྷ'),
    (0xF58, 'V'),
    (0xF5C, 'M', 'ཛྷ'),
    (0xF5D, 'V'),
    (0xF69, 'M', 'ཀྵ'),
    (0xF6A, 'V'),
    (0xF6D, 'X'),
    (0xF71, 'V'),
    (0xF73, 'M', 'ཱི'),
    (0xF74, 'V'),
    (0xF75, 'M', 'ཱུ'),
    (0xF76, 'M', 'ྲྀ'),
    (0xF77, 'M', 'ྲཱྀ'),
    (0xF78, 'M', 'ླྀ'),
    (0xF79, 'M', 'ླཱྀ'),
    (0xF7A, 'V'),
    (0xF81, 'M', 'ཱྀ'),
    (0xF82, 'V'),
    (0xF93, 'M', 'ྒྷ'),
    (0xF94, 'V'),
    (0xF98, 'X'),
    (0xF99, 'V'),
    (0xF9D, 'M', 'ྜྷ'),
    (0xF9E, 'V'),
    (0xFA2, 'M', 'ྡྷ'),
    (0xFA3, 'V'),
    (0xFA7, 'M', 'ྦྷ'),
    (0xFA8, 'V'),
    (0xFAC, 'M', 'ྫྷ'),
    (0xFAD, 'V'),
    (0xFB9, 'M', 'ྐྵ'),
    (0xFBA, 'V'),
    (0xFBD, 'X'),
    (0xFBE, 'V'),
    (0xFCD, 'X'),
    (0xFCE, 'V'),
    (0xFDB, 'X'),
    (0x1000, 'V'),
    (0x10A0, 'X'),
    (0x10C7, 'M', 'ⴧ'),
    (0x10C8, 'X'),
    (0x10CD, 'M', 'ⴭ'),
    (0x10CE, 'X'),
    (0x10D0, 'V'),
    (0x10FC, 'M', 'ნ'),
    (0x10FD, 'V'),
    (0x115F, 'X'),
    (0x1161, 'V'),
    (0x1249, 'X'),
    (0x124A, 'V'),
    (0x124E, 'X'),
    (0x1250, 'V'),
    (0x1257, 'X'),
    (0x1258, 'V'),
    (0x1259, 'X'),
    (0x125A, 'V'),
    (0x125E, 'X'),
    (0x1260, 'V'),
    (0x1289, 'X'),
    (0x128A, 'V'),
    (0x128E, 'X'),
    (0x1290, 'V'),
    (0x12B1, 'X'),
    (0x12B2, 'V'),
    (0x12B6, 'X'),
    (0x12B8, 'V'),
    (0x12BF, 'X'),
    (0x12C0, 'V'),
    (0x12C1, 'X'),
    (0x12C2, 'V'),
    (0x12C6, 'X'),
    (0x12C8, 'V'),
    (0x12D7, 'X'),
    (0x12D8, 'V'),
    (0x1311, 'X'),
    (0x1312, 'V'),
    ]

def _seg_14() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1316, 'X'),
    (0x1318, 'V'),
    (0x135B, 'X'),
    (0x135D, 'V'),
    (0x137D, 'X'),
    (0x1380, 'V'),
    (0x139A, 'X'),
    (0x13A0, 'V'),
    (0x13F6, 'X'),
    (0x13F8, 'M', 'Ᏸ'),
    (0x13F9, 'M', 'Ᏹ'),
    (0x13FA, 'M', 'Ᏺ'),
    (0x13FB, 'M', 'Ᏻ'),
    (0x13FC, 'M', 'Ᏼ'),
    (0x13FD, 'M', 'Ᏽ'),
    (0x13FE, 'X'),
    (0x1400, 'V'),
    (0x1680, 'X'),
    (0x1681, 'V'),
    (0x169D, 'X'),
    (0x16A0, 'V'),
    (0x16F9, 'X'),
    (0x1700, 'V'),
    (0x1716, 'X'),
    (0x171F, 'V'),
    (0x1737, 'X'),
    (0x1740, 'V'),
    (0x1754, 'X'),
    (0x1760, 'V'),
    (0x176D, 'X'),
    (0x176E, 'V'),
    (0x1771, 'X'),
    (0x1772, 'V'),
    (0x1774, 'X'),
    (0x1780, 'V'),
    (0x17B4, 'X'),
    (0x17B6, 'V'),
    (0x17DE, 'X'),
    (0x17E0, 'V'),
    (0x17EA, 'X'),
    (0x17F0, 'V'),
    (0x17FA, 'X'),
    (0x1800, 'V'),
    (0x1806, 'X'),
    (0x1807, 'V'),
    (0x180B, 'I'),
    (0x180E, 'X'),
    (0x180F, 'I'),
    (0x1810, 'V'),
    (0x181A, 'X'),
    (0x1820, 'V'),
    (0x1879, 'X'),
    (0x1880, 'V'),
    (0x18AB, 'X'),
    (0x18B0, 'V'),
    (0x18F6, 'X'),
    (0x1900, 'V'),
    (0x191F, 'X'),
    (0x1920, 'V'),
    (0x192C, 'X'),
    (0x1930, 'V'),
    (0x193C, 'X'),
    (0x1940, 'V'),
    (0x1941, 'X'),
    (0x1944, 'V'),
    (0x196E, 'X'),
    (0x1970, 'V'),
    (0x1975, 'X'),
    (0x1980, 'V'),
    (0x19AC, 'X'),
    (0x19B0, 'V'),
    (0x19CA, 'X'),
    (0x19D0, 'V'),
    (0x19DB, 'X'),
    (0x19DE, 'V'),
    (0x1A1C, 'X'),
    (0x1A1E, 'V'),
    (0x1A5F, 'X'),
    (0x1A60, 'V'),
    (0x1A7D, 'X'),
    (0x1A7F, 'V'),
    (0x1A8A, 'X'),
    (0x1A90, 'V'),
    (0x1A9A, 'X'),
    (0x1AA0, 'V'),
    (0x1AAE, 'X'),
    (0x1AB0, 'V'),
    (0x1ACF, 'X'),
    (0x1B00, 'V'),
    (0x1B4D, 'X'),
    (0x1B50, 'V'),
    (0x1B7F, 'X'),
    (0x1B80, 'V'),
    (0x1BF4, 'X'),
    (0x1BFC, 'V'),
    (0x1C38, 'X'),
    (0x1C3B, 'V'),
    (0x1C4A, 'X'),
    (0x1C4D, 'V'),
    (0x1C80, 'M', 'в'),
    ]

def _seg_15() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1C81, 'M', 'д'),
    (0x1C82, 'M', 'о'),
    (0x1C83, 'M', 'с'),
    (0x1C84, 'M', 'т'),
    (0x1C86, 'M', 'ъ'),
    (0x1C87, 'M', 'ѣ'),
    (0x1C88, 'M', 'ꙋ'),
    (0x1C89, 'X'),
    (0x1C90, 'M', 'ა'),
    (0x1C91, 'M', 'ბ'),
    (0x1C92, 'M', 'გ'),
    (0x1C93, 'M', 'დ'),
    (0x1C94, 'M', 'ე'),
    (0x1C95, 'M', 'ვ'),
    (0x1C96, 'M', 'ზ'),
    (0x1C97, 'M', 'თ'),
    (0x1C98, 'M', 'ი'),
    (0x1C99, 'M', 'კ'),
    (0x1C9A, 'M', 'ლ'),
    (0x1C9B, 'M', 'მ'),
    (0x1C9C, 'M', 'ნ'),
    (0x1C9D, 'M', 'ო'),
    (0x1C9E, 'M', 'პ'),
    (0x1C9F, 'M', 'ჟ'),
    (0x1CA0, 'M', 'რ'),
    (0x1CA1, 'M', 'ს'),
    (0x1CA2, 'M', 'ტ'),
    (0x1CA3, 'M', 'უ'),
    (0x1CA4, 'M', 'ფ'),
    (0x1CA5, 'M', 'ქ'),
    (0x1CA6, 'M', 'ღ'),
    (0x1CA7, 'M', 'ყ'),
    (0x1CA8, 'M', 'შ'),
    (0x1CA9, 'M', 'ჩ'),
    (0x1CAA, 'M', 'ც'),
    (0x1CAB, 'M', 'ძ'),
    (0x1CAC, 'M', 'წ'),
    (0x1CAD, 'M', 'ჭ'),
    (0x1CAE, 'M', 'ხ'),
    (0x1CAF, 'M', 'ჯ'),
    (0x1CB0, 'M', 'ჰ'),
    (0x1CB1, 'M', 'ჱ'),
    (0x1CB2, 'M', 'ჲ'),
    (0x1CB3, 'M', 'ჳ'),
    (0x1CB4, 'M', 'ჴ'),
    (0x1CB5, 'M', 'ჵ'),
    (0x1CB6, 'M', 'ჶ'),
    (0x1CB7, 'M', 'ჷ'),
    (0x1CB8, 'M', 'ჸ'),
    (0x1CB9, 'M', 'ჹ'),
    (0x1CBA, 'M', 'ჺ'),
    (0x1CBB, 'X'),
    (0x1CBD, 'M', 'ჽ'),
    (0x1CBE, 'M', 'ჾ'),
    (0x1CBF, 'M', 'ჿ'),
    (0x1CC0, 'V'),
    (0x1CC8, 'X'),
    (0x1CD0, 'V'),
    (0x1CFB, 'X'),
    (0x1D00, 'V'),
    (0x1D2C, 'M', 'a'),
    (0x1D2D, 'M', 'æ'),
    (0x1D2E, 'M', 'b'),
    (0x1D2F, 'V'),
    (0x1D30, 'M', 'd'),
    (0x1D31, 'M', 'e'),
    (0x1D32, 'M', 'ǝ'),
    (0x1D33, 'M', 'g'),
    (0x1D34, 'M', 'h'),
    (0x1D35, 'M', 'i'),
    (0x1D36, 'M', 'j'),
    (0x1D37, 'M', 'k'),
    (0x1D38, 'M', 'l'),
    (0x1D39, 'M', 'm'),
    (0x1D3A, 'M', 'n'),
    (0x1D3B, 'V'),
    (0x1D3C, 'M', 'o'),
    (0x1D3D, 'M', 'ȣ'),
    (0x1D3E, 'M', 'p'),
    (0x1D3F, 'M', 'r'),
    (0x1D40, 'M', 't'),
    (0x1D41, 'M', 'u'),
    (0x1D42, 'M', 'w'),
    (0x1D43, 'M', 'a'),
    (0x1D44, 'M', 'ɐ'),
    (0x1D45, 'M', 'ɑ'),
    (0x1D46, 'M', 'ᴂ'),
    (0x1D47, 'M', 'b'),
    (0x1D48, 'M', 'd'),
    (0x1D49, 'M', 'e'),
    (0x1D4A, 'M', 'ə'),
    (0x1D4B, 'M', 'ɛ'),
    (0x1D4C, 'M', 'ɜ'),
    (0x1D4D, 'M', 'g'),
    (0x1D4E, 'V'),
    (0x1D4F, 'M', 'k'),
    (0x1D50, 'M', 'm'),
    (0x1D51, 'M', 'ŋ'),
    (0x1D52, 'M', 'o'),
    (0x1D53, 'M', 'ɔ'),
    ]

def _seg_16() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1D54, 'M', 'ᴖ'),
    (0x1D55, 'M', 'ᴗ'),
    (0x1D56, 'M', 'p'),
    (0x1D57, 'M', 't'),
    (0x1D58, 'M', 'u'),
    (0x1D59, 'M', 'ᴝ'),
    (0x1D5A, 'M', 'ɯ'),
    (0x1D5B, 'M', 'v'),
    (0x1D5C, 'M', 'ᴥ'),
    (0x1D5D, 'M', 'β'),
    (0x1D5E, 'M', 'γ'),
    (0x1D5F, 'M', 'δ'),
    (0x1D60, 'M', 'φ'),
    (0x1D61, 'M', 'χ'),
    (0x1D62, 'M', 'i'),
    (0x1D63, 'M', 'r'),
    (0x1D64, 'M', 'u'),
    (0x1D65, 'M', 'v'),
    (0x1D66, 'M', 'β'),
    (0x1D67, 'M', 'γ'),
    (0x1D68, 'M', 'ρ'),
    (0x1D69, 'M', 'φ'),
    (0x1D6A, 'M', 'χ'),
    (0x1D6B, 'V'),
    (0x1D78, 'M', 'н'),
    (0x1D79, 'V'),
    (0x1D9B, 'M', 'ɒ'),
    (0x1D9C, 'M', 'c'),
    (0x1D9D, 'M', 'ɕ'),
    (0x1D9E, 'M', 'ð'),
    (0x1D9F, 'M', 'ɜ'),
    (0x1DA0, 'M', 'f'),
    (0x1DA1, 'M', 'ɟ'),
    (0x1DA2, 'M', 'ɡ'),
    (0x1DA3, 'M', 'ɥ'),
    (0x1DA4, 'M', 'ɨ'),
    (0x1DA5, 'M', 'ɩ'),
    (0x1DA6, 'M', 'ɪ'),
    (0x1DA7, 'M', 'ᵻ'),
    (0x1DA8, 'M', 'ʝ'),
    (0x1DA9, 'M', 'ɭ'),
    (0x1DAA, 'M', 'ᶅ'),
    (0x1DAB, 'M', 'ʟ'),
    (0x1DAC, 'M', 'ɱ'),
    (0x1DAD, 'M', 'ɰ'),
    (0x1DAE, 'M', 'ɲ'),
    (0x1DAF, 'M', 'ɳ'),
    (0x1DB0, 'M', 'ɴ'),
    (0x1DB1, 'M', 'ɵ'),
    (0x1DB2, 'M', 'ɸ'),
    (0x1DB3, 'M', 'ʂ'),
    (0x1DB4, 'M', 'ʃ'),
    (0x1DB5, 'M', 'ƫ'),
    (0x1DB6, 'M', 'ʉ'),
    (0x1DB7, 'M', 'ʊ'),
    (0x1DB8, 'M', 'ᴜ'),
    (0x1DB9, 'M', 'ʋ'),
    (0x1DBA, 'M', 'ʌ'),
    (0x1DBB, 'M', 'z'),
    (0x1DBC, 'M', 'ʐ'),
    (0x1DBD, 'M', 'ʑ'),
    (0x1DBE, 'M', 'ʒ'),
    (0x1DBF, 'M', 'θ'),
    (0x1DC0, 'V'),
    (0x1E00, 'M', 'ḁ'),
    (0x1E01, 'V'),
    (0x1E02, 'M', 'ḃ'),
    (0x1E03, 'V'),
    (0x1E04, 'M', 'ḅ'),
    (0x1E05, 'V'),
    (0x1E06, 'M', 'ḇ'),
    (0x1E07, 'V'),
    (0x1E08, 'M', 'ḉ'),
    (0x1E09, 'V'),
    (0x1E0A, 'M', 'ḋ'),
    (0x1E0B, 'V'),
    (0x1E0C, 'M', 'ḍ'),
    (0x1E0D, 'V'),
    (0x1E0E, 'M', 'ḏ'),
    (0x1E0F, 'V'),
    (0x1E10, 'M', 'ḑ'),
    (0x1E11, 'V'),
    (0x1E12, 'M', 'ḓ'),
    (0x1E13, 'V'),
    (0x1E14, 'M', 'ḕ'),
    (0x1E15, 'V'),
    (0x1E16, 'M', 'ḗ'),
    (0x1E17, 'V'),
    (0x1E18, 'M', 'ḙ'),
    (0x1E19, 'V'),
    (0x1E1A, 'M', 'ḛ'),
    (0x1E1B, 'V'),
    (0x1E1C, 'M', 'ḝ'),
    (0x1E1D, 'V'),
    (0x1E1E, 'M', 'ḟ'),
    (0x1E1F, 'V'),
    (0x1E20, 'M', 'ḡ'),
    (0x1E21, 'V'),
    (0x1E22, 'M', 'ḣ'),
    (0x1E23, 'V'),
    ]

def _seg_17() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1E24, 'M', 'ḥ'),
    (0x1E25, 'V'),
    (0x1E26, 'M', 'ḧ'),
    (0x1E27, 'V'),
    (0x1E28, 'M', 'ḩ'),
    (0x1E29, 'V'),
    (0x1E2A, 'M', 'ḫ'),
    (0x1E2B, 'V'),
    (0x1E2C, 'M', 'ḭ'),
    (0x1E2D, 'V'),
    (0x1E2E, 'M', 'ḯ'),
    (0x1E2F, 'V'),
    (0x1E30, 'M', 'ḱ'),
    (0x1E31, 'V'),
    (0x1E32, 'M', 'ḳ'),
    (0x1E33, 'V'),
    (0x1E34, 'M', 'ḵ'),
    (0x1E35, 'V'),
    (0x1E36, 'M', 'ḷ'),
    (0x1E37, 'V'),
    (0x1E38, 'M', 'ḹ'),
    (0x1E39, 'V'),
    (0x1E3A, 'M', 'ḻ'),
    (0x1E3B, 'V'),
    (0x1E3C, 'M', 'ḽ'),
    (0x1E3D, 'V'),
    (0x1E3E, 'M', 'ḿ'),
    (0x1E3F, 'V'),
    (0x1E40, 'M', 'ṁ'),
    (0x1E41, 'V'),
    (0x1E42, 'M', 'ṃ'),
    (0x1E43, 'V'),
    (0x1E44, 'M', 'ṅ'),
    (0x1E45, 'V'),
    (0x1E46, 'M', 'ṇ'),
    (0x1E47, 'V'),
    (0x1E48, 'M', 'ṉ'),
    (0x1E49, 'V'),
    (0x1E4A, 'M', 'ṋ'),
    (0x1E4B, 'V'),
    (0x1E4C, 'M', 'ṍ'),
    (0x1E4D, 'V'),
    (0x1E4E, 'M', 'ṏ'),
    (0x1E4F, 'V'),
    (0x1E50, 'M', 'ṑ'),
    (0x1E51, 'V'),
    (0x1E52, 'M', 'ṓ'),
    (0x1E53, 'V'),
    (0x1E54, 'M', 'ṕ'),
    (0x1E55, 'V'),
    (0x1E56, 'M', 'ṗ'),
    (0x1E57, 'V'),
    (0x1E58, 'M', 'ṙ'),
    (0x1E59, 'V'),
    (0x1E5A, 'M', 'ṛ'),
    (0x1E5B, 'V'),
    (0x1E5C, 'M', 'ṝ'),
    (0x1E5D, 'V'),
    (0x1E5E, 'M', 'ṟ'),
    (0x1E5F, 'V'),
    (0x1E60, 'M', 'ṡ'),
    (0x1E61, 'V'),
    (0x1E62, 'M', 'ṣ'),
    (0x1E63, 'V'),
    (0x1E64, 'M', 'ṥ'),
    (0x1E65, 'V'),
    (0x1E66, 'M', 'ṧ'),
    (0x1E67, 'V'),
    (0x1E68, 'M', 'ṩ'),
    (0x1E69, 'V'),
    (0x1E6A, 'M', 'ṫ'),
    (0x1E6B, 'V'),
    (0x1E6C, 'M', 'ṭ'),
    (0x1E6D, 'V'),
    (0x1E6E, 'M', 'ṯ'),
    (0x1E6F, 'V'),
    (0x1E70, 'M', 'ṱ'),
    (0x1E71, 'V'),
    (0x1E72, 'M', 'ṳ'),
    (0x1E73, 'V'),
    (0x1E74, 'M', 'ṵ'),
    (0x1E75, 'V'),
    (0x1E76, 'M', 'ṷ'),
    (0x1E77, 'V'),
    (0x1E78, 'M', 'ṹ'),
    (0x1E79, 'V'),
    (0x1E7A, 'M', 'ṻ'),
    (0x1E7B, 'V'),
    (0x1E7C, 'M', 'ṽ'),
    (0x1E7D, 'V'),
    (0x1E7E, 'M', 'ṿ'),
    (0x1E7F, 'V'),
    (0x1E80, 'M', 'ẁ'),
    (0x1E81, 'V'),
    (0x1E82, 'M', 'ẃ'),
    (0x1E83, 'V'),
    (0x1E84, 'M', 'ẅ'),
    (0x1E85, 'V'),
    (0x1E86, 'M', 'ẇ'),
    (0x1E87, 'V'),
    ]

def _seg_18() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1E88, 'M', 'ẉ'),
    (0x1E89, 'V'),
    (0x1E8A, 'M', 'ẋ'),
    (0x1E8B, 'V'),
    (0x1E8C, 'M', 'ẍ'),
    (0x1E8D, 'V'),
    (0x1E8E, 'M', 'ẏ'),
    (0x1E8F, 'V'),
    (0x1E90, 'M', 'ẑ'),
    (0x1E91, 'V'),
    (0x1E92, 'M', 'ẓ'),
    (0x1E93, 'V'),
    (0x1E94, 'M', 'ẕ'),
    (0x1E95, 'V'),
    (0x1E9A, 'M', 'aʾ'),
    (0x1E9B, 'M', 'ṡ'),
    (0x1E9C, 'V'),
    (0x1E9E, 'M', 'ß'),
    (0x1E9F, 'V'),
    (0x1EA0, 'M', 'ạ'),
    (0x1EA1, 'V'),
    (0x1EA2, 'M', 'ả'),
    (0x1EA3, 'V'),
    (0x1EA4, 'M', 'ấ'),
    (0x1EA5, 'V'),
    (0x1EA6, 'M', 'ầ'),
    (0x1EA7, 'V'),
    (0x1EA8, 'M', 'ẩ'),
    (0x1EA9, 'V'),
    (0x1EAA, 'M', 'ẫ'),
    (0x1EAB, 'V'),
    (0x1EAC, 'M', 'ậ'),
    (0x1EAD, 'V'),
    (0x1EAE, 'M', 'ắ'),
    (0x1EAF, 'V'),
    (0x1EB0, 'M', 'ằ'),
    (0x1EB1, 'V'),
    (0x1EB2, 'M', 'ẳ'),
    (0x1EB3, 'V'),
    (0x1EB4, 'M', 'ẵ'),
    (0x1EB5, 'V'),
    (0x1EB6, 'M', 'ặ'),
    (0x1EB7, 'V'),
    (0x1EB8, 'M', 'ẹ'),
    (0x1EB9, 'V'),
    (0x1EBA, 'M', 'ẻ'),
    (0x1EBB, 'V'),
    (0x1EBC, 'M', 'ẽ'),
    (0x1EBD, 'V'),
    (0x1EBE, 'M', 'ế'),
    (0x1EBF, 'V'),
    (0x1EC0, 'M', 'ề'),
    (0x1EC1, 'V'),
    (0x1EC2, 'M', 'ể'),
    (0x1EC3, 'V'),
    (0x1EC4, 'M', 'ễ'),
    (0x1EC5, 'V'),
    (0x1EC6, 'M', 'ệ'),
    (0x1EC7, 'V'),
    (0x1EC8, 'M', 'ỉ'),
    (0x1EC9, 'V'),
    (0x1ECA, 'M', 'ị'),
    (0x1ECB, 'V'),
    (0x1ECC, 'M', 'ọ'),
    (0x1ECD, 'V'),
    (0x1ECE, 'M', 'ỏ'),
    (0x1ECF, 'V'),
    (0x1ED0, 'M', 'ố'),
    (0x1ED1, 'V'),
    (0x1ED2, 'M', 'ồ'),
    (0x1ED3, 'V'),
    (0x1ED4, 'M', 'ổ'),
    (0x1ED5, 'V'),
    (0x1ED6, 'M', 'ỗ'),
    (0x1ED7, 'V'),
    (0x1ED8, 'M', 'ộ'),
    (0x1ED9, 'V'),
    (0x1EDA, 'M', 'ớ'),
    (0x1EDB, 'V'),
    (0x1EDC, 'M', 'ờ'),
    (0x1EDD, 'V'),
    (0x1EDE, 'M', 'ở'),
    (0x1EDF, 'V'),
    (0x1EE0, 'M', 'ỡ'),
    (0x1EE1, 'V'),
    (0x1EE2, 'M', 'ợ'),
    (0x1EE3, 'V'),
    (0x1EE4, 'M', 'ụ'),
    (0x1EE5, 'V'),
    (0x1EE6, 'M', 'ủ'),
    (0x1EE7, 'V'),
    (0x1EE8, 'M', 'ứ'),
    (0x1EE9, 'V'),
    (0x1EEA, 'M', 'ừ'),
    (0x1EEB, 'V'),
    (0x1EEC, 'M', 'ử'),
    (0x1EED, 'V'),
    (0x1EEE, 'M', 'ữ'),
    (0x1EEF, 'V'),
    (0x1EF0, 'M', 'ự'),
    ]

def _seg_19() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1EF1, 'V'),
    (0x1EF2, 'M', 'ỳ'),
    (0x1EF3, 'V'),
    (0x1EF4, 'M', 'ỵ'),
    (0x1EF5, 'V'),
    (0x1EF6, 'M', 'ỷ'),
    (0x1EF7, 'V'),
    (0x1EF8, 'M', 'ỹ'),
    (0x1EF9, 'V'),
    (0x1EFA, 'M', 'ỻ'),
    (0x1EFB, 'V'),
    (0x1EFC, 'M', 'ỽ'),
    (0x1EFD, 'V'),
    (0x1EFE, 'M', 'ỿ'),
    (0x1EFF, 'V'),
    (0x1F08, 'M', 'ἀ'),
    (0x1F09, 'M', 'ἁ'),
    (0x1F0A, 'M', 'ἂ'),
    (0x1F0B, 'M', 'ἃ'),
    (0x1F0C, 'M', 'ἄ'),
    (0x1F0D, 'M', 'ἅ'),
    (0x1F0E, 'M', 'ἆ'),
    (0x1F0F, 'M', 'ἇ'),
    (0x1F10, 'V'),
    (0x1F16, 'X'),
    (0x1F18, 'M', 'ἐ'),
    (0x1F19, 'M', 'ἑ'),
    (0x1F1A, 'M', 'ἒ'),
    (0x1F1B, 'M', 'ἓ'),
    (0x1F1C, 'M', 'ἔ'),
    (0x1F1D, 'M', 'ἕ'),
    (0x1F1E, 'X'),
    (0x1F20, 'V'),
    (0x1F28, 'M', 'ἠ'),
    (0x1F29, 'M', 'ἡ'),
    (0x1F2A, 'M', 'ἢ'),
    (0x1F2B, 'M', 'ἣ'),
    (0x1F2C, 'M', 'ἤ'),
    (0x1F2D, 'M', 'ἥ'),
    (0x1F2E, 'M', 'ἦ'),
    (0x1F2F, 'M', 'ἧ'),
    (0x1F30, 'V'),
    (0x1F38, 'M', 'ἰ'),
    (0x1F39, 'M', 'ἱ'),
    (0x1F3A, 'M', 'ἲ'),
    (0x1F3B, 'M', 'ἳ'),
    (0x1F3C, 'M', 'ἴ'),
    (0x1F3D, 'M', 'ἵ'),
    (0x1F3E, 'M', 'ἶ'),
    (0x1F3F, 'M', 'ἷ'),
    (0x1F40, 'V'),
    (0x1F46, 'X'),
    (0x1F48, 'M', 'ὀ'),
    (0x1F49, 'M', 'ὁ'),
    (0x1F4A, 'M', 'ὂ'),
    (0x1F4B, 'M', 'ὃ'),
    (0x1F4C, 'M', 'ὄ'),
    (0x1F4D, 'M', 'ὅ'),
    (0x1F4E, 'X'),
    (0x1F50, 'V'),
    (0x1F58, 'X'),
    (0x1F59, 'M', 'ὑ'),
    (0x1F5A, 'X'),
    (0x1F5B, 'M', 'ὓ'),
    (0x1F5C, 'X'),
    (0x1F5D, 'M', 'ὕ'),
    (0x1F5E, 'X'),
    (0x1F5F, 'M', 'ὗ'),
    (0x1F60, 'V'),
    (0x1F68, 'M', 'ὠ'),
    (0x1F69, 'M', 'ὡ'),
    (0x1F6A, 'M', 'ὢ'),
    (0x1F6B, 'M', 'ὣ'),
    (0x1F6C, 'M', 'ὤ'),
    (0x1F6D, 'M', 'ὥ'),
    (0x1F6E, 'M', 'ὦ'),
    (0x1F6F, 'M', 'ὧ'),
    (0x1F70, 'V'),
    (0x1F71, 'M', 'ά'),
    (0x1F72, 'V'),
    (0x1F73, 'M', 'έ'),
    (0x1F74, 'V'),
    (0x1F75, 'M', 'ή'),
    (0x1F76, 'V'),
    (0x1F77, 'M', 'ί'),
    (0x1F78, 'V'),
    (0x1F79, 'M', 'ό'),
    (0x1F7A, 'V'),
    (0x1F7B, 'M', 'ύ'),
    (0x1F7C, 'V'),
    (0x1F7D, 'M', 'ώ'),
    (0x1F7E, 'X'),
    (0x1F80, 'M', 'ἀι'),
    (0x1F81, 'M', 'ἁι'),
    (0x1F82, 'M', 'ἂι'),
    (0x1F83, 'M', 'ἃι'),
    (0x1F84, 'M', 'ἄι'),
    (0x1F85, 'M', 'ἅι'),
    (0x1F86, 'M', 'ἆι'),
    (0x1F87, 'M', 'ἇι'),
    ]

def _seg_20() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1F88, 'M', 'ἀι'),
    (0x1F89, 'M', 'ἁι'),
    (0x1F8A, 'M', 'ἂι'),
    (0x1F8B, 'M', 'ἃι'),
    (0x1F8C, 'M', 'ἄι'),
    (0x1F8D, 'M', 'ἅι'),
    (0x1F8E, 'M', 'ἆι'),
    (0x1F8F, 'M', 'ἇι'),
    (0x1F90, 'M', 'ἠι'),
    (0x1F91, 'M', 'ἡι'),
    (0x1F92, 'M', 'ἢι'),
    (0x1F93, 'M', 'ἣι'),
    (0x1F94, 'M', 'ἤι'),
    (0x1F95, 'M', 'ἥι'),
    (0x1F96, 'M', 'ἦι'),
    (0x1F97, 'M', 'ἧι'),
    (0x1F98, 'M', 'ἠι'),
    (0x1F99, 'M', 'ἡι'),
    (0x1F9A, 'M', 'ἢι'),
    (0x1F9B, 'M', 'ἣι'),
    (0x1F9C, 'M', 'ἤι'),
    (0x1F9D, 'M', 'ἥι'),
    (0x1F9E, 'M', 'ἦι'),
    (0x1F9F, 'M', 'ἧι'),
    (0x1FA0, 'M', 'ὠι'),
    (0x1FA1, 'M', 'ὡι'),
    (0x1FA2, 'M', 'ὢι'),
    (0x1FA3, 'M', 'ὣι'),
    (0x1FA4, 'M', 'ὤι'),
    (0x1FA5, 'M', 'ὥι'),
    (0x1FA6, 'M', 'ὦι'),
    (0x1FA7, 'M', 'ὧι'),
    (0x1FA8, 'M', 'ὠι'),
    (0x1FA9, 'M', 'ὡι'),
    (0x1FAA, 'M', 'ὢι'),
    (0x1FAB, 'M', 'ὣι'),
    (0x1FAC, 'M', 'ὤι'),
    (0x1FAD, 'M', 'ὥι'),
    (0x1FAE, 'M', 'ὦι'),
    (0x1FAF, 'M', 'ὧι'),
    (0x1FB0, 'V'),
    (0x1FB2, 'M', 'ὰι'),
    (0x1FB3, 'M', 'αι'),
    (0x1FB4, 'M', 'άι'),
    (0x1FB5, 'X'),
    (0x1FB6, 'V'),
    (0x1FB7, 'M', 'ᾶι'),
    (0x1FB8, 'M', 'ᾰ'),
    (0x1FB9, 'M', 'ᾱ'),
    (0x1FBA, 'M', 'ὰ'),
    (0x1FBB, 'M', 'ά'),
    (0x1FBC, 'M', 'αι'),
    (0x1FBD, '3', ' ̓'),
    (0x1FBE, 'M', 'ι'),
    (0x1FBF, '3', ' ̓'),
    (0x1FC0, '3', ' ͂'),
    (0x1FC1, '3', ' ̈͂'),
    (0x1FC2, 'M', 'ὴι'),
    (0x1FC3, 'M', 'ηι'),
    (0x1FC4, 'M', 'ήι'),
    (0x1FC5, 'X'),
    (0x1FC6, 'V'),
    (0x1FC7, 'M', 'ῆι'),
    (0x1FC8, 'M', 'ὲ'),
    (0x1FC9, 'M', 'έ'),
    (0x1FCA, 'M', 'ὴ'),
    (0x1FCB, 'M', 'ή'),
    (0x1FCC, 'M', 'ηι'),
    (0x1FCD, '3', ' ̓̀'),
    (0x1FCE, '3', ' ̓́'),
    (0x1FCF, '3', ' ̓͂'),
    (0x1FD0, 'V'),
    (0x1FD3, 'M', 'ΐ'),
    (0x1FD4, 'X'),
    (0x1FD6, 'V'),
    (0x1FD8, 'M', 'ῐ'),
    (0x1FD9, 'M', 'ῑ'),
    (0x1FDA, 'M', 'ὶ'),
    (0x1FDB, 'M', 'ί'),
    (0x1FDC, 'X'),
    (0x1FDD, '3', ' ̔̀'),
    (0x1FDE, '3', ' ̔́'),
    (0x1FDF, '3', ' ̔͂'),
    (0x1FE0, 'V'),
    (0x1FE3, 'M', 'ΰ'),
    (0x1FE4, 'V'),
    (0x1FE8, 'M', 'ῠ'),
    (0x1FE9, 'M', 'ῡ'),
    (0x1FEA, 'M', 'ὺ'),
    (0x1FEB, 'M', 'ύ'),
    (0x1FEC, 'M', 'ῥ'),
    (0x1FED, '3', ' ̈̀'),
    (0x1FEE, '3', ' ̈́'),
    (0x1FEF, '3', '`'),
    (0x1FF0, 'X'),
    (0x1FF2, 'M', 'ὼι'),
    (0x1FF3, 'M', 'ωι'),
    (0x1FF4, 'M', 'ώι'),
    (0x1FF5, 'X'),
    (0x1FF6, 'V'),
    ]

def _seg_21() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1FF7, 'M', 'ῶι'),
    (0x1FF8, 'M', 'ὸ'),
    (0x1FF9, 'M', 'ό'),
    (0x1FFA, 'M', 'ὼ'),
    (0x1FFB, 'M', 'ώ'),
    (0x1FFC, 'M', 'ωι'),
    (0x1FFD, '3', ' ́'),
    (0x1FFE, '3', ' ̔'),
    (0x1FFF, 'X'),
    (0x2000, '3', ' '),
    (0x200B, 'I'),
    (0x200C, 'D', ''),
    (0x200E, 'X'),
    (0x2010, 'V'),
    (0x2011, 'M', '‐'),
    (0x2012, 'V'),
    (0x2017, '3', ' ̳'),
    (0x2018, 'V'),
    (0x2024, 'X'),
    (0x2027, 'V'),
    (0x2028, 'X'),
    (0x202F, '3', ' '),
    (0x2030, 'V'),
    (0x2033, 'M', '′′'),
    (0x2034, 'M', '′′′'),
    (0x2035, 'V'),
    (0x2036, 'M', '‵‵'),
    (0x2037, 'M', '‵‵‵'),
    (0x2038, 'V'),
    (0x203C, '3', '!!'),
    (0x203D, 'V'),
    (0x203E, '3', ' ̅'),
    (0x203F, 'V'),
    (0x2047, '3', '??'),
    (0x2048, '3', '?!'),
    (0x2049, '3', '!?'),
    (0x204A, 'V'),
    (0x2057, 'M', '′′′′'),
    (0x2058, 'V'),
    (0x205F, '3', ' '),
    (0x2060, 'I'),
    (0x2061, 'X'),
    (0x2064, 'I'),
    (0x2065, 'X'),
    (0x2070, 'M', '0'),
    (0x2071, 'M', 'i'),
    (0x2072, 'X'),
    (0x2074, 'M', '4'),
    (0x2075, 'M', '5'),
    (0x2076, 'M', '6'),
    (0x2077, 'M', '7'),
    (0x2078, 'M', '8'),
    (0x2079, 'M', '9'),
    (0x207A, '3', '+'),
    (0x207B, 'M', '−'),
    (0x207C, '3', '='),
    (0x207D, '3', '('),
    (0x207E, '3', ')'),
    (0x207F, 'M', 'n'),
    (0x2080, 'M', '0'),
    (0x2081, 'M', '1'),
    (0x2082, 'M', '2'),
    (0x2083, 'M', '3'),
    (0x2084, 'M', '4'),
    (0x2085, 'M', '5'),
    (0x2086, 'M', '6'),
    (0x2087, 'M', '7'),
    (0x2088, 'M', '8'),
    (0x2089, 'M', '9'),
    (0x208A, '3', '+'),
    (0x208B, 'M', '−'),
    (0x208C, '3', '='),
    (0x208D, '3', '('),
    (0x208E, '3', ')'),
    (0x208F, 'X'),
    (0x2090, 'M', 'a'),
    (0x2091, 'M', 'e'),
    (0x2092, 'M', 'o'),
    (0x2093, 'M', 'x'),
    (0x2094, 'M', 'ə'),
    (0x2095, 'M', 'h'),
    (0x2096, 'M', 'k'),
    (0x2097, 'M', 'l'),
    (0x2098, 'M', 'm'),
    (0x2099, 'M', 'n'),
    (0x209A, 'M', 'p'),
    (0x209B, 'M', 's'),
    (0x209C, 'M', 't'),
    (0x209D, 'X'),
    (0x20A0, 'V'),
    (0x20A8, 'M', 'rs'),
    (0x20A9, 'V'),
    (0x20C1, 'X'),
    (0x20D0, 'V'),
    (0x20F1, 'X'),
    (0x2100, '3', 'a/c'),
    (0x2101, '3', 'a/s'),
    (0x2102, 'M', 'c'),
    (0x2103, 'M', '°c'),
    (0x2104, 'V'),
    ]

def _seg_22() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x2105, '3', 'c/o'),
    (0x2106, '3', 'c/u'),
    (0x2107, 'M', 'ɛ'),
    (0x2108, 'V'),
    (0x2109, 'M', '°f'),
    (0x210A, 'M', 'g'),
    (0x210B, 'M', 'h'),
    (0x210F, 'M', 'ħ'),
    (0x2110, 'M', 'i'),
    (0x2112, 'M', 'l'),
    (0x2114, 'V'),
    (0x2115, 'M', 'n'),
    (0x2116, 'M', 'no'),
    (0x2117, 'V'),
    (0x2119, 'M', 'p'),
    (0x211A, 'M', 'q'),
    (0x211B, 'M', 'r'),
    (0x211E, 'V'),
    (0x2120, 'M', 'sm'),
    (0x2121, 'M', 'tel'),
    (0x2122, 'M', 'tm'),
    (0x2123, 'V'),
    (0x2124, 'M', 'z'),
    (0x2125, 'V'),
    (0x2126, 'M', 'ω'),
    (0x2127, 'V'),
    (0x2128, 'M', 'z'),
    (0x2129, 'V'),
    (0x212A, 'M', 'k'),
    (0x212B, 'M', 'å'),
    (0x212C, 'M', 'b'),
    (0x212D, 'M', 'c'),
    (0x212E, 'V'),
    (0x212F, 'M', 'e'),
    (0x2131, 'M', 'f'),
    (0x2132, 'X'),
    (0x2133, 'M', 'm'),
    (0x2134, 'M', 'o'),
    (0x2135, 'M', 'א'),
    (0x2136, 'M', 'ב'),
    (0x2137, 'M', 'ג'),
    (0x2138, 'M', 'ד'),
    (0x2139, 'M', 'i'),
    (0x213A, 'V'),
    (0x213B, 'M', 'fax'),
    (0x213C, 'M', 'π'),
    (0x213D, 'M', 'γ'),
    (0x213F, 'M', 'π'),
    (0x2140, 'M', '∑'),
    (0x2141, 'V'),
    (0x2145, 'M', 'd'),
    (0x2147, 'M', 'e'),
    (0x2148, 'M', 'i'),
    (0x2149, 'M', 'j'),
    (0x214A, 'V'),
    (0x2150, 'M', '1⁄7'),
    (0x2151, 'M', '1⁄9'),
    (0x2152, 'M', '1⁄10'),
    (0x2153, 'M', '1⁄3'),
    (0x2154, 'M', '2⁄3'),
    (0x2155, 'M', '1⁄5'),
    (0x2156, 'M', '2⁄5'),
    (0x2157, 'M', '3⁄5'),
    (0x2158, 'M', '4⁄5'),
    (0x2159, 'M', '1⁄6'),
    (0x215A, 'M', '5⁄6'),
    (0x215B, 'M', '1⁄8'),
    (0x215C, 'M', '3⁄8'),
    (0x215D, 'M', '5⁄8'),
    (0x215E, 'M', '7⁄8'),
    (0x215F, 'M', '1⁄'),
    (0x2160, 'M', 'i'),
    (0x2161, 'M', 'ii'),
    (0x2162, 'M', 'iii'),
    (0x2163, 'M', 'iv'),
    (0x2164, 'M', 'v'),
    (0x2165, 'M', 'vi'),
    (0x2166, 'M', 'vii'),
    (0x2167, 'M', 'viii'),
    (0x2168, 'M', 'ix'),
    (0x2169, 'M', 'x'),
    (0x216A, 'M', 'xi'),
    (0x216B, 'M', 'xii'),
    (0x216C, 'M', 'l'),
    (0x216D, 'M', 'c'),
    (0x216E, 'M', 'd'),
    (0x216F, 'M', 'm'),
    (0x2170, 'M', 'i'),
    (0x2171, 'M', 'ii'),
    (0x2172, 'M', 'iii'),
    (0x2173, 'M', 'iv'),
    (0x2174, 'M', 'v'),
    (0x2175, 'M', 'vi'),
    (0x2176, 'M', 'vii'),
    (0x2177, 'M', 'viii'),
    (0x2178, 'M', 'ix'),
    (0x2179, 'M', 'x'),
    (0x217A, 'M', 'xi'),
    (0x217B, 'M', 'xii'),
    (0x217C, 'M', 'l'),
    ]

def _seg_23() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x217D, 'M', 'c'),
    (0x217E, 'M', 'd'),
    (0x217F, 'M', 'm'),
    (0x2180, 'V'),
    (0x2183, 'X'),
    (0x2184, 'V'),
    (0x2189, 'M', '0⁄3'),
    (0x218A, 'V'),
    (0x218C, 'X'),
    (0x2190, 'V'),
    (0x222C, 'M', '∫∫'),
    (0x222D, 'M', '∫∫∫'),
    (0x222E, 'V'),
    (0x222F, 'M', '∮∮'),
    (0x2230, 'M', '∮∮∮'),
    (0x2231, 'V'),
    (0x2329, 'M', '〈'),
    (0x232A, 'M', '〉'),
    (0x232B, 'V'),
    (0x2427, 'X'),
    (0x2440, 'V'),
    (0x244B, 'X'),
    (0x2460, 'M', '1'),
    (0x2461, 'M', '2'),
    (0x2462, 'M', '3'),
    (0x2463, 'M', '4'),
    (0x2464, 'M', '5'),
    (0x2465, 'M', '6'),
    (0x2466, 'M', '7'),
    (0x2467, 'M', '8'),
    (0x2468, 'M', '9'),
    (0x2469, 'M', '10'),
    (0x246A, 'M', '11'),
    (0x246B, 'M', '12'),
    (0x246C, 'M', '13'),
    (0x246D, 'M', '14'),
    (0x246E, 'M', '15'),
    (0x246F, 'M', '16'),
    (0x2470, 'M', '17'),
    (0x2471, 'M', '18'),
    (0x2472, 'M', '19'),
    (0x2473, 'M', '20'),
    (0x2474, '3', '(1)'),
    (0x2475, '3', '(2)'),
    (0x2476, '3', '(3)'),
    (0x2477, '3', '(4)'),
    (0x2478, '3', '(5)'),
    (0x2479, '3', '(6)'),
    (0x247A, '3', '(7)'),
    (0x247B, '3', '(8)'),
    (0x247C, '3', '(9)'),
    (0x247D, '3', '(10)'),
    (0x247E, '3', '(11)'),
    (0x247F, '3', '(12)'),
    (0x2480, '3', '(13)'),
    (0x2481, '3', '(14)'),
    (0x2482, '3', '(15)'),
    (0x2483, '3', '(16)'),
    (0x2484, '3', '(17)'),
    (0x2485, '3', '(18)'),
    (0x2486, '3', '(19)'),
    (0x2487, '3', '(20)'),
    (0x2488, 'X'),
    (0x249C, '3', '(a)'),
    (0x249D, '3', '(b)'),
    (0x249E, '3', '(c)'),
    (0x249F, '3', '(d)'),
    (0x24A0, '3', '(e)'),
    (0x24A1, '3', '(f)'),
    (0x24A2, '3', '(g)'),
    (0x24A3, '3', '(h)'),
    (0x24A4, '3', '(i)'),
    (0x24A5, '3', '(j)'),
    (0x24A6, '3', '(k)'),
    (0x24A7, '3', '(l)'),
    (0x24A8, '3', '(m)'),
    (0x24A9, '3', '(n)'),
    (0x24AA, '3', '(o)'),
    (0x24AB, '3', '(p)'),
    (0x24AC, '3', '(q)'),
    (0x24AD, '3', '(r)'),
    (0x24AE, '3', '(s)'),
    (0x24AF, '3', '(t)'),
    (0x24B0, '3', '(u)'),
    (0x24B1, '3', '(v)'),
    (0x24B2, '3', '(w)'),
    (0x24B3, '3', '(x)'),
    (0x24B4, '3', '(y)'),
    (0x24B5, '3', '(z)'),
    (0x24B6, 'M', 'a'),
    (0x24B7, 'M', 'b'),
    (0x24B8, 'M', 'c'),
    (0x24B9, 'M', 'd'),
    (0x24BA, 'M', 'e'),
    (0x24BB, 'M', 'f'),
    (0x24BC, 'M', 'g'),
    (0x24BD, 'M', 'h'),
    (0x24BE, 'M', 'i'),
    (0x24BF, 'M', 'j'),
    (0x24C0, 'M', 'k'),
    ]

def _seg_24() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x24C1, 'M', 'l'),
    (0x24C2, 'M', 'm'),
    (0x24C3, 'M', 'n'),
    (0x24C4, 'M', 'o'),
    (0x24C5, 'M', 'p'),
    (0x24C6, 'M', 'q'),
    (0x24C7, 'M', 'r'),
    (0x24C8, 'M', 's'),
    (0x24C9, 'M', 't'),
    (0x24CA, 'M', 'u'),
    (0x24CB, 'M', 'v'),
    (0x24CC, 'M', 'w'),
    (0x24CD, 'M', 'x'),
    (0x24CE, 'M', 'y'),
    (0x24CF, 'M', 'z'),
    (0x24D0, 'M', 'a'),
    (0x24D1, 'M', 'b'),
    (0x24D2, 'M', 'c'),
    (0x24D3, 'M', 'd'),
    (0x24D4, 'M', 'e'),
    (0x24D5, 'M', 'f'),
    (0x24D6, 'M', 'g'),
    (0x24D7, 'M', 'h'),
    (0x24D8, 'M', 'i'),
    (0x24D9, 'M', 'j'),
    (0x24DA, 'M', 'k'),
    (0x24DB, 'M', 'l'),
    (0x24DC, 'M', 'm'),
    (0x24DD, 'M', 'n'),
    (0x24DE, 'M', 'o'),
    (0x24DF, 'M', 'p'),
    (0x24E0, 'M', 'q'),
    (0x24E1, 'M', 'r'),
    (0x24E2, 'M', 's'),
    (0x24E3, 'M', 't'),
    (0x24E4, 'M', 'u'),
    (0x24E5, 'M', 'v'),
    (0x24E6, 'M', 'w'),
    (0x24E7, 'M', 'x'),
    (0x24E8, 'M', 'y'),
    (0x24E9, 'M', 'z'),
    (0x24EA, 'M', '0'),
    (0x24EB, 'V'),
    (0x2A0C, 'M', '∫∫∫∫'),
    (0x2A0D, 'V'),
    (0x2A74, '3', '::='),
    (0x2A75, '3', '=='),
    (0x2A76, '3', '==='),
    (0x2A77, 'V'),
    (0x2ADC, 'M', '⫝̸'),
    (0x2ADD, 'V'),
    (0x2B74, 'X'),
    (0x2B76, 'V'),
    (0x2B96, 'X'),
    (0x2B97, 'V'),
    (0x2C00, 'M', 'ⰰ'),
    (0x2C01, 'M', 'ⰱ'),
    (0x2C02, 'M', 'ⰲ'),
    (0x2C03, 'M', 'ⰳ'),
    (0x2C04, 'M', 'ⰴ'),
    (0x2C05, 'M', 'ⰵ'),
    (0x2C06, 'M', 'ⰶ'),
    (0x2C07, 'M', 'ⰷ'),
    (0x2C08, 'M', 'ⰸ'),
    (0x2C09, 'M', 'ⰹ'),
    (0x2C0A, 'M', 'ⰺ'),
    (0x2C0B, 'M', 'ⰻ'),
    (0x2C0C, 'M', 'ⰼ'),
    (0x2C0D, 'M', 'ⰽ'),
    (0x2C0E, 'M', 'ⰾ'),
    (0x2C0F, 'M', 'ⰿ'),
    (0x2C10, 'M', 'ⱀ'),
    (0x2C11, 'M', 'ⱁ'),
    (0x2C12, 'M', 'ⱂ'),
    (0x2C13, 'M', 'ⱃ'),
    (0x2C14, 'M', 'ⱄ'),
    (0x2C15, 'M', 'ⱅ'),
    (0x2C16, 'M', 'ⱆ'),
    (0x2C17, 'M', 'ⱇ'),
    (0x2C18, 'M', 'ⱈ'),
    (0x2C19, 'M', 'ⱉ'),
    (0x2C1A, 'M', 'ⱊ'),
    (0x2C1B, 'M', 'ⱋ'),
    (0x2C1C, 'M', 'ⱌ'),
    (0x2C1D, 'M', 'ⱍ'),
    (0x2C1E, 'M', 'ⱎ'),
    (0x2C1F, 'M', 'ⱏ'),
    (0x2C20, 'M', 'ⱐ'),
    (0x2C21, 'M', 'ⱑ'),
    (0x2C22, 'M', 'ⱒ'),
    (0x2C23, 'M', 'ⱓ'),
    (0x2C24, 'M', 'ⱔ'),
    (0x2C25, 'M', 'ⱕ'),
    (0x2C26, 'M', 'ⱖ'),
    (0x2C27, 'M', 'ⱗ'),
    (0x2C28, 'M', 'ⱘ'),
    (0x2C29, 'M', 'ⱙ'),
    (0x2C2A, 'M', 'ⱚ'),
    (0x2C2B, 'M', 'ⱛ'),
    (0x2C2C, 'M', 'ⱜ'),
    ]

def _seg_25() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x2C2D, 'M', 'ⱝ'),
    (0x2C2E, 'M', 'ⱞ'),
    (0x2C2F, 'M', 'ⱟ'),
    (0x2C30, 'V'),
    (0x2C60, 'M', 'ⱡ'),
    (0x2C61, 'V'),
    (0x2C62, 'M', 'ɫ'),
    (0x2C63, 'M', 'ᵽ'),
    (0x2C64, 'M', 'ɽ'),
    (0x2C65, 'V'),
    (0x2C67, 'M', 'ⱨ'),
    (0x2C68, 'V'),
    (0x2C69, 'M', 'ⱪ'),
    (0x2C6A, 'V'),
    (0x2C6B, 'M', 'ⱬ'),
    (0x2C6C, 'V'),
    (0x2C6D, 'M', 'ɑ'),
    (0x2C6E, 'M', 'ɱ'),
    (0x2C6F, 'M', 'ɐ'),
    (0x2C70, 'M', 'ɒ'),
    (0x2C71, 'V'),
    (0x2C72, 'M', 'ⱳ'),
    (0x2C73, 'V'),
    (0x2C75, 'M', 'ⱶ'),
    (0x2C76, 'V'),
    (0x2C7C, 'M', 'j'),
    (0x2C7D, 'M', 'v'),
    (0x2C7E, 'M', 'ȿ'),
    (0x2C7F, 'M', 'ɀ'),
    (0x2C80, 'M', 'ⲁ'),
    (0x2C81, 'V'),
    (0x2C82, 'M', 'ⲃ'),
    (0x2C83, 'V'),
    (0x2C84, 'M', 'ⲅ'),
    (0x2C85, 'V'),
    (0x2C86, 'M', 'ⲇ'),
    (0x2C87, 'V'),
    (0x2C88, 'M', 'ⲉ'),
    (0x2C89, 'V'),
    (0x2C8A, 'M', 'ⲋ'),
    (0x2C8B, 'V'),
    (0x2C8C, 'M', 'ⲍ'),
    (0x2C8D, 'V'),
    (0x2C8E, 'M', 'ⲏ'),
    (0x2C8F, 'V'),
    (0x2C90, 'M', 'ⲑ'),
    (0x2C91, 'V'),
    (0x2C92, 'M', 'ⲓ'),
    (0x2C93, 'V'),
    (0x2C94, 'M', 'ⲕ'),
    (0x2C95, 'V'),
    (0x2C96, 'M', 'ⲗ'),
    (0x2C97, 'V'),
    (0x2C98, 'M', 'ⲙ'),
    (0x2C99, 'V'),
    (0x2C9A, 'M', 'ⲛ'),
    (0x2C9B, 'V'),
    (0x2C9C, 'M', 'ⲝ'),
    (0x2C9D, 'V'),
    (0x2C9E, 'M', 'ⲟ'),
    (0x2C9F, 'V'),
    (0x2CA0, 'M', 'ⲡ'),
    (0x2CA1, 'V'),
    (0x2CA2, 'M', 'ⲣ'),
    (0x2CA3, 'V'),
    (0x2CA4, 'M', 'ⲥ'),
    (0x2CA5, 'V'),
    (0x2CA6, 'M', 'ⲧ'),
    (0x2CA7, 'V'),
    (0x2CA8, 'M', 'ⲩ'),
    (0x2CA9, 'V'),
    (0x2CAA, 'M', 'ⲫ'),
    (0x2CAB, 'V'),
    (0x2CAC, 'M', 'ⲭ'),
    (0x2CAD, 'V'),
    (0x2CAE, 'M', 'ⲯ'),
    (0x2CAF, 'V'),
    (0x2CB0, 'M', 'ⲱ'),
    (0x2CB1, 'V'),
    (0x2CB2, 'M', 'ⲳ'),
    (0x2CB3, 'V'),
    (0x2CB4, 'M', 'ⲵ'),
    (0x2CB5, 'V'),
    (0x2CB6, 'M', 'ⲷ'),
    (0x2CB7, 'V'),
    (0x2CB8, 'M', 'ⲹ'),
    (0x2CB9, 'V'),
    (0x2CBA, 'M', 'ⲻ'),
    (0x2CBB, 'V'),
    (0x2CBC, 'M', 'ⲽ'),
    (0x2CBD, 'V'),
    (0x2CBE, 'M', 'ⲿ'),
    (0x2CBF, 'V'),
    (0x2CC0, 'M', 'ⳁ'),
    (0x2CC1, 'V'),
    (0x2CC2, 'M', 'ⳃ'),
    (0x2CC3, 'V'),
    (0x2CC4, 'M', 'ⳅ'),
    (0x2CC5, 'V'),
    (0x2CC6, 'M', 'ⳇ'),
    ]

def _seg_26() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x2CC7, 'V'),
    (0x2CC8, 'M', 'ⳉ'),
    (0x2CC9, 'V'),
    (0x2CCA, 'M', 'ⳋ'),
    (0x2CCB, 'V'),
    (0x2CCC, 'M', 'ⳍ'),
    (0x2CCD, 'V'),
    (0x2CCE, 'M', 'ⳏ'),
    (0x2CCF, 'V'),
    (0x2CD0, 'M', 'ⳑ'),
    (0x2CD1, 'V'),
    (0x2CD2, 'M', 'ⳓ'),
    (0x2CD3, 'V'),
    (0x2CD4, 'M', 'ⳕ'),
    (0x2CD5, 'V'),
    (0x2CD6, 'M', 'ⳗ'),
    (0x2CD7, 'V'),
    (0x2CD8, 'M', 'ⳙ'),
    (0x2CD9, 'V'),
    (0x2CDA, 'M', 'ⳛ'),
    (0x2CDB, 'V'),
    (0x2CDC, 'M', 'ⳝ'),
    (0x2CDD, 'V'),
    (0x2CDE, 'M', 'ⳟ'),
    (0x2CDF, 'V'),
    (0x2CE0, 'M', 'ⳡ'),
    (0x2CE1, 'V'),
    (0x2CE2, 'M', 'ⳣ'),
    (0x2CE3, 'V'),
    (0x2CEB, 'M', 'ⳬ'),
    (0x2CEC, 'V'),
    (0x2CED, 'M', 'ⳮ'),
    (0x2CEE, 'V'),
    (0x2CF2, 'M', 'ⳳ'),
    (0x2CF3, 'V'),
    (0x2CF4, 'X'),
    (0x2CF9, 'V'),
    (0x2D26, 'X'),
    (0x2D27, 'V'),
    (0x2D28, 'X'),
    (0x2D2D, 'V'),
    (0x2D2E, 'X'),
    (0x2D30, 'V'),
    (0x2D68, 'X'),
    (0x2D6F, 'M', 'ⵡ'),
    (0x2D70, 'V'),
    (0x2D71, 'X'),
    (0x2D7F, 'V'),
    (0x2D97, 'X'),
    (0x2DA0, 'V'),
    (0x2DA7, 'X'),
    (0x2DA8, 'V'),
    (0x2DAF, 'X'),
    (0x2DB0, 'V'),
    (0x2DB7, 'X'),
    (0x2DB8, 'V'),
    (0x2DBF, 'X'),
    (0x2DC0, 'V'),
    (0x2DC7, 'X'),
    (0x2DC8, 'V'),
    (0x2DCF, 'X'),
    (0x2DD0, 'V'),
    (0x2DD7, 'X'),
    (0x2DD8, 'V'),
    (0x2DDF, 'X'),
    (0x2DE0, 'V'),
    (0x2E5E, 'X'),
    (0x2E80, 'V'),
    (0x2E9A, 'X'),
    (0x2E9B, 'V'),
    (0x2E9F, 'M', '母'),
    (0x2EA0, 'V'),
    (0x2EF3, 'M', '龟'),
    (0x2EF4, 'X'),
    (0x2F00, 'M', '一'),
    (0x2F01, 'M', '丨'),
    (0x2F02, 'M', '丶'),
    (0x2F03, 'M', '丿'),
    (0x2F04, 'M', '乙'),
    (0x2F05, 'M', '亅'),
    (0x2F06, 'M', '二'),
    (0x2F07, 'M', '亠'),
    (0x2F08, 'M', '人'),
    (0x2F09, 'M', '儿'),
    (0x2F0A, 'M', '入'),
    (0x2F0B, 'M', '八'),
    (0x2F0C, 'M', '冂'),
    (0x2F0D, 'M', '冖'),
    (0x2F0E, 'M', '冫'),
    (0x2F0F, 'M', '几'),
    (0x2F10, 'M', '凵'),
    (0x2F11, 'M', '刀'),
    (0x2F12, 'M', '力'),
    (0x2F13, 'M', '勹'),
    (0x2F14, 'M', '匕'),
    (0x2F15, 'M', '匚'),
    (0x2F16, 'M', '匸'),
    (0x2F17, 'M', '十'),
    (0x2F18, 'M', '卜'),
    (0x2F19, 'M', '卩'),
    ]

def _seg_27() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x2F1A, 'M', '厂'),
    (0x2F1B, 'M', '厶'),
    (0x2F1C, 'M', '又'),
    (0x2F1D, 'M', '口'),
    (0x2F1E, 'M', '囗'),
    (0x2F1F, 'M', '土'),
    (0x2F20, 'M', '士'),
    (0x2F21, 'M', '夂'),
    (0x2F22, 'M', '夊'),
    (0x2F23, 'M', '夕'),
    (0x2F24, 'M', '大'),
    (0x2F25, 'M', '女'),
    (0x2F26, 'M', '子'),
    (0x2F27, 'M', '宀'),
    (0x2F28, 'M', '寸'),
    (0x2F29, 'M', '小'),
    (0x2F2A, 'M', '尢'),
    (0x2F2B, 'M', '尸'),
    (0x2F2C, 'M', '屮'),
    (0x2F2D, 'M', '山'),
    (0x2F2E, 'M', '巛'),
    (0x2F2F, 'M', '工'),
    (0x2F30, 'M', '己'),
    (0x2F31, 'M', '巾'),
    (0x2F32, 'M', '干'),
    (0x2F33, 'M', '幺'),
    (0x2F34, 'M', '广'),
    (0x2F35, 'M', '廴'),
    (0x2F36, 'M', '廾'),
    (0x2F37, 'M', '弋'),
    (0x2F38, 'M', '弓'),
    (0x2F39, 'M', '彐'),
    (0x2F3A, 'M', '彡'),
    (0x2F3B, 'M', '彳'),
    (0x2F3C, 'M', '心'),
    (0x2F3D, 'M', '戈'),
    (0x2F3E, 'M', '戶'),
    (0x2F3F, 'M', '手'),
    (0x2F40, 'M', '支'),
    (0x2F41, 'M', '攴'),
    (0x2F42, 'M', '文'),
    (0x2F43, 'M', '斗'),
    (0x2F44, 'M', '斤'),
    (0x2F45, 'M', '方'),
    (0x2F46, 'M', '无'),
    (0x2F47, 'M', '日'),
    (0x2F48, 'M', '曰'),
    (0x2F49, 'M', '月'),
    (0x2F4A, 'M', '木'),
    (0x2F4B, 'M', '欠'),
    (0x2F4C, 'M', '止'),
    (0x2F4D, 'M', '歹'),
    (0x2F4E, 'M', '殳'),
    (0x2F4F, 'M', '毋'),
    (0x2F50, 'M', '比'),
    (0x2F51, 'M', '毛'),
    (0x2F52, 'M', '氏'),
    (0x2F53, 'M', '气'),
    (0x2F54, 'M', '水'),
    (0x2F55, 'M', '火'),
    (0x2F56, 'M', '爪'),
    (0x2F57, 'M', '父'),
    (0x2F58, 'M', '爻'),
    (0x2F59, 'M', '爿'),
    (0x2F5A, 'M', '片'),
    (0x2F5B, 'M', '牙'),
    (0x2F5C, 'M', '牛'),
    (0x2F5D, 'M', '犬'),
    (0x2F5E, 'M', '玄'),
    (0x2F5F, 'M', '玉'),
    (0x2F60, 'M', '瓜'),
    (0x2F61, 'M', '瓦'),
    (0x2F62, 'M', '甘'),
    (0x2F63, 'M', '生'),
    (0x2F64, 'M', '用'),
    (0x2F65, 'M', '田'),
    (0x2F66, 'M', '疋'),
    (0x2F67, 'M', '疒'),
    (0x2F68, 'M', '癶'),
    (0x2F69, 'M', '白'),
    (0x2F6A, 'M', '皮'),
    (0x2F6B, 'M', '皿'),
    (0x2F6C, 'M', '目'),
    (0x2F6D, 'M', '矛'),
    (0x2F6E, 'M', '矢'),
    (0x2F6F, 'M', '石'),
    (0x2F70, 'M', '示'),
    (0x2F71, 'M', '禸'),
    (0x2F72, 'M', '禾'),
    (0x2F73, 'M', '穴'),
    (0x2F74, 'M', '立'),
    (0x2F75, 'M', '竹'),
    (0x2F76, 'M', '米'),
    (0x2F77, 'M', '糸'),
    (0x2F78, 'M', '缶'),
    (0x2F79, 'M', '网'),
    (0x2F7A, 'M', '羊'),
    (0x2F7B, 'M', '羽'),
    (0x2F7C, 'M', '老'),
    (0x2F7D, 'M', '而'),
    ]

def _seg_28() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x2F7E, 'M', '耒'),
    (0x2F7F, 'M', '耳'),
    (0x2F80, 'M', '聿'),
    (0x2F81, 'M', '肉'),
    (0x2F82, 'M', '臣'),
    (0x2F83, 'M', '自'),
    (0x2F84, 'M', '至'),
    (0x2F85, 'M', '臼'),
    (0x2F86, 'M', '舌'),
    (0x2F87, 'M', '舛'),
    (0x2F88, 'M', '舟'),
    (0x2F89, 'M', '艮'),
    (0x2F8A, 'M', '色'),
    (0x2F8B, 'M', '艸'),
    (0x2F8C, 'M', '虍'),
    (0x2F8D, 'M', '虫'),
    (0x2F8E, 'M', '血'),
    (0x2F8F, 'M', '行'),
    (0x2F90, 'M', '衣'),
    (0x2F91, 'M', '襾'),
    (0x2F92, 'M', '見'),
    (0x2F93, 'M', '角'),
    (0x2F94, 'M', '言'),
    (0x2F95, 'M', '谷'),
    (0x2F96, 'M', '豆'),
    (0x2F97, 'M', '豕'),
    (0x2F98, 'M', '豸'),
    (0x2F99, 'M', '貝'),
    (0x2F9A, 'M', '赤'),
    (0x2F9B, 'M', '走'),
    (0x2F9C, 'M', '足'),
    (0x2F9D, 'M', '身'),
    (0x2F9E, 'M', '車'),
    (0x2F9F, 'M', '辛'),
    (0x2FA0, 'M', '辰'),
    (0x2FA1, 'M', '辵'),
    (0x2FA2, 'M', '邑'),
    (0x2FA3, 'M', '酉'),
    (0x2FA4, 'M', '釆'),
    (0x2FA5, 'M', '里'),
    (0x2FA6, 'M', '金'),
    (0x2FA7, 'M', '長'),
    (0x2FA8, 'M', '門'),
    (0x2FA9, 'M', '阜'),
    (0x2FAA, 'M', '隶'),
    (0x2FAB, 'M', '隹'),
    (0x2FAC, 'M', '雨'),
    (0x2FAD, 'M', '靑'),
    (0x2FAE, 'M', '非'),
    (0x2FAF, 'M', '面'),
    (0x2FB0, 'M', '革'),
    (0x2FB1, 'M', '韋'),
    (0x2FB2, 'M', '韭'),
    (0x2FB3, 'M', '音'),
    (0x2FB4, 'M', '頁'),
    (0x2FB5, 'M', '風'),
    (0x2FB6, 'M', '飛'),
    (0x2FB7, 'M', '食'),
    (0x2FB8, 'M', '首'),
    (0x2FB9, 'M', '香'),
    (0x2FBA, 'M', '馬'),
    (0x2FBB, 'M', '骨'),
    (0x2FBC, 'M', '高'),
    (0x2FBD, 'M', '髟'),
    (0x2FBE, 'M', '鬥'),
    (0x2FBF, 'M', '鬯'),
    (0x2FC0, 'M', '鬲'),
    (0x2FC1, 'M', '鬼'),
    (0x2FC2, 'M', '魚'),
    (0x2FC3, 'M', '鳥'),
    (0x2FC4, 'M', '鹵'),
    (0x2FC5, 'M', '鹿'),
    (0x2FC6, 'M', '麥'),
    (0x2FC7, 'M', '麻'),
    (0x2FC8, 'M', '黃'),
    (0x2FC9, 'M', '黍'),
    (0x2FCA, 'M', '黑'),
    (0x2FCB, 'M', '黹'),
    (0x2FCC, 'M', '黽'),
    (0x2FCD, 'M', '鼎'),
    (0x2FCE, 'M', '鼓'),
    (0x2FCF, 'M', '鼠'),
    (0x2FD0, 'M', '鼻'),
    (0x2FD1, 'M', '齊'),
    (0x2FD2, 'M', '齒'),
    (0x2FD3, 'M', '龍'),
    (0x2FD4, 'M', '龜'),
    (0x2FD5, 'M', '龠'),
    (0x2FD6, 'X'),
    (0x3000, '3', ' '),
    (0x3001, 'V'),
    (0x3002, 'M', '.'),
    (0x3003, 'V'),
    (0x3036, 'M', '〒'),
    (0x3037, 'V'),
    (0x3038, 'M', '十'),
    (0x3039, 'M', '卄'),
    (0x303A, 'M', '卅'),
    (0x303B, 'V'),
    (0x3040, 'X'),
    ]

def _seg_29() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x3041, 'V'),
    (0x3097, 'X'),
    (0x3099, 'V'),
    (0x309B, '3', ' ゙'),
    (0x309C, '3', ' ゚'),
    (0x309D, 'V'),
    (0x309F, 'M', 'より'),
    (0x30A0, 'V'),
    (0x30FF, 'M', 'コト'),
    (0x3100, 'X'),
    (0x3105, 'V'),
    (0x3130, 'X'),
    (0x3131, 'M', 'ᄀ'),
    (0x3132, 'M', 'ᄁ'),
    (0x3133, 'M', 'ᆪ'),
    (0x3134, 'M', 'ᄂ'),
    (0x3135, 'M', 'ᆬ'),
    (0x3136, 'M', 'ᆭ'),
    (0x3137, 'M', 'ᄃ'),
    (0x3138, 'M', 'ᄄ'),
    (0x3139, 'M', 'ᄅ'),
    (0x313A, 'M', 'ᆰ'),
    (0x313B, 'M', 'ᆱ'),
    (0x313C, 'M', 'ᆲ'),
    (0x313D, 'M', 'ᆳ'),
    (0x313E, 'M', 'ᆴ'),
    (0x313F, 'M', 'ᆵ'),
    (0x3140, 'M', 'ᄚ'),
    (0x3141, 'M', 'ᄆ'),
    (0x3142, 'M', 'ᄇ'),
    (0x3143, 'M', 'ᄈ'),
    (0x3144, 'M', 'ᄡ'),
    (0x3145, 'M', 'ᄉ'),
    (0x3146, 'M', 'ᄊ'),
    (0x3147, 'M', 'ᄋ'),
    (0x3148, 'M', 'ᄌ'),
    (0x3149, 'M', 'ᄍ'),
    (0x314A, 'M', 'ᄎ'),
    (0x314B, 'M', 'ᄏ'),
    (0x314C, 'M', 'ᄐ'),
    (0x314D, 'M', 'ᄑ'),
    (0x314E, 'M', 'ᄒ'),
    (0x314F, 'M', 'ᅡ'),
    (0x3150, 'M', 'ᅢ'),
    (0x3151, 'M', 'ᅣ'),
    (0x3152, 'M', 'ᅤ'),
    (0x3153, 'M', 'ᅥ'),
    (0x3154, 'M', 'ᅦ'),
    (0x3155, 'M', 'ᅧ'),
    (0x3156, 'M', 'ᅨ'),
    (0x3157, 'M', 'ᅩ'),
    (0x3158, 'M', 'ᅪ'),
    (0x3159, 'M', 'ᅫ'),
    (0x315A, 'M', 'ᅬ'),
    (0x315B, 'M', 'ᅭ'),
    (0x315C, 'M', 'ᅮ'),
    (0x315D, 'M', 'ᅯ'),
    (0x315E, 'M', 'ᅰ'),
    (0x315F, 'M', 'ᅱ'),
    (0x3160, 'M', 'ᅲ'),
    (0x3161, 'M', 'ᅳ'),
    (0x3162, 'M', 'ᅴ'),
    (0x3163, 'M', 'ᅵ'),
    (0x3164, 'X'),
    (0x3165, 'M', 'ᄔ'),
    (0x3166, 'M', 'ᄕ'),
    (0x3167, 'M', 'ᇇ'),
    (0x3168, 'M', 'ᇈ'),
    (0x3169, 'M', 'ᇌ'),
    (0x316A, 'M', 'ᇎ'),
    (0x316B, 'M', 'ᇓ'),
    (0x316C, 'M', 'ᇗ'),
    (0x316D, 'M', 'ᇙ'),
    (0x316E, 'M', 'ᄜ'),
    (0x316F, 'M', 'ᇝ'),
    (0x3170, 'M', 'ᇟ'),
    (0x3171, 'M', 'ᄝ'),
    (0x3172, 'M', 'ᄞ'),
    (0x3173, 'M', 'ᄠ'),
    (0x3174, 'M', 'ᄢ'),
    (0x3175, 'M', 'ᄣ'),
    (0x3176, 'M', 'ᄧ'),
    (0x3177, 'M', 'ᄩ'),
    (0x3178, 'M', 'ᄫ'),
    (0x3179, 'M', 'ᄬ'),
    (0x317A, 'M', 'ᄭ'),
    (0x317B, 'M', 'ᄮ'),
    (0x317C, 'M', 'ᄯ'),
    (0x317D, 'M', 'ᄲ'),
    (0x317E, 'M', 'ᄶ'),
    (0x317F, 'M', 'ᅀ'),
    (0x3180, 'M', 'ᅇ'),
    (0x3181, 'M', 'ᅌ'),
    (0x3182, 'M', 'ᇱ'),
    (0x3183, 'M', 'ᇲ'),
    (0x3184, 'M', 'ᅗ'),
    (0x3185, 'M', 'ᅘ'),
    (0x3186, 'M', 'ᅙ'),
    (0x3187, 'M', 'ᆄ'),
    (0x3188, 'M', 'ᆅ'),
    ]

def _seg_30() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x3189, 'M', 'ᆈ'),
    (0x318A, 'M', 'ᆑ'),
    (0x318B, 'M', 'ᆒ'),
    (0x318C, 'M', 'ᆔ'),
    (0x318D, 'M', 'ᆞ'),
    (0x318E, 'M', 'ᆡ'),
    (0x318F, 'X'),
    (0x3190, 'V'),
    (0x3192, 'M', '一'),
    (0x3193, 'M', '二'),
    (0x3194, 'M', '三'),
    (0x3195, 'M', '四'),
    (0x3196, 'M', '上'),
    (0x3197, 'M', '中'),
    (0x3198, 'M', '下'),
    (0x3199, 'M', '甲'),
    (0x319A, 'M', '乙'),
    (0x319B, 'M', '丙'),
    (0x319C, 'M', '丁'),
    (0x319D, 'M', '天'),
    (0x319E, 'M', '地'),
    (0x319F, 'M', '人'),
    (0x31A0, 'V'),
    (0x31E4, 'X'),
    (0x31F0, 'V'),
    (0x3200, '3', '(ᄀ)'),
    (0x3201, '3', '(ᄂ)'),
    (0x3202, '3', '(ᄃ)'),
    (0x3203, '3', '(ᄅ)'),
    (0x3204, '3', '(ᄆ)'),
    (0x3205, '3', '(ᄇ)'),
    (0x3206, '3', '(ᄉ)'),
    (0x3207, '3', '(ᄋ)'),
    (0x3208, '3', '(ᄌ)'),
    (0x3209, '3', '(ᄎ)'),
    (0x320A, '3', '(ᄏ)'),
    (0x320B, '3', '(ᄐ)'),
    (0x320C, '3', '(ᄑ)'),
    (0x320D, '3', '(ᄒ)'),
    (0x320E, '3', '(가)'),
    (0x320F, '3', '(나)'),
    (0x3210, '3', '(다)'),
    (0x3211, '3', '(라)'),
    (0x3212, '3', '(마)'),
    (0x3213, '3', '(바)'),
    (0x3214, '3', '(사)'),
    (0x3215, '3', '(아)'),
    (0x3216, '3', '(자)'),
    (0x3217, '3', '(차)'),
    (0x3218, '3', '(카)'),
    (0x3219, '3', '(타)'),
    (0x321A, '3', '(파)'),
    (0x321B, '3', '(하)'),
    (0x321C, '3', '(주)'),
    (0x321D, '3', '(오전)'),
    (0x321E, '3', '(오후)'),
    (0x321F, 'X'),
    (0x3220, '3', '(一)'),
    (0x3221, '3', '(二)'),
    (0x3222, '3', '(三)'),
    (0x3223, '3', '(四)'),
    (0x3224, '3', '(五)'),
    (0x3225, '3', '(六)'),
    (0x3226, '3', '(七)'),
    (0x3227, '3', '(八)'),
    (0x3228, '3', '(九)'),
    (0x3229, '3', '(十)'),
    (0x322A, '3', '(月)'),
    (0x322B, '3', '(火)'),
    (0x322C, '3', '(水)'),
    (0x322D, '3', '(木)'),
    (0x322E, '3', '(金)'),
    (0x322F, '3', '(土)'),
    (0x3230, '3', '(日)'),
    (0x3231, '3', '(株)'),
    (0x3232, '3', '(有)'),
    (0x3233, '3', '(社)'),
    (0x3234, '3', '(名)'),
    (0x3235, '3', '(特)'),
    (0x3236, '3', '(財)'),
    (0x3237, '3', '(祝)'),
    (0x3238, '3', '(労)'),
    (0x3239, '3', '(代)'),
    (0x323A, '3', '(呼)'),
    (0x323B, '3', '(学)'),
    (0x323C, '3', '(監)'),
    (0x323D, '3', '(企)'),
    (0x323E, '3', '(資)'),
    (0x323F, '3', '(協)'),
    (0x3240, '3', '(祭)'),
    (0x3241, '3', '(休)'),
    (0x3242, '3', '(自)'),
    (0x3243, '3', '(至)'),
    (0x3244, 'M', '問'),
    (0x3245, 'M', '幼'),
    (0x3246, 'M', '文'),
    (0x3247, 'M', '箏'),
    (0x3248, 'V'),
    (0x3250, 'M', 'pte'),
    (0x3251, 'M', '21'),
    ]

def _seg_31() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x3252, 'M', '22'),
    (0x3253, 'M', '23'),
    (0x3254, 'M', '24'),
    (0x3255, 'M', '25'),
    (0x3256, 'M', '26'),
    (0x3257, 'M', '27'),
    (0x3258, 'M', '28'),
    (0x3259, 'M', '29'),
    (0x325A, 'M', '30'),
    (0x325B, 'M', '31'),
    (0x325C, 'M', '32'),
    (0x325D, 'M', '33'),
    (0x325E, 'M', '34'),
    (0x325F, 'M', '35'),
    (0x3260, 'M', 'ᄀ'),
    (0x3261, 'M', 'ᄂ'),
    (0x3262, 'M', 'ᄃ'),
    (0x3263, 'M', 'ᄅ'),
    (0x3264, 'M', 'ᄆ'),
    (0x3265, 'M', 'ᄇ'),
    (0x3266, 'M', 'ᄉ'),
    (0x3267, 'M', 'ᄋ'),
    (0x3268, 'M', 'ᄌ'),
    (0x3269, 'M', 'ᄎ'),
    (0x326A, 'M', 'ᄏ'),
    (0x326B, 'M', 'ᄐ'),
    (0x326C, 'M', 'ᄑ'),
    (0x326D, 'M', 'ᄒ'),
    (0x326E, 'M', '가'),
    (0x326F, 'M', '나'),
    (0x3270, 'M', '다'),
    (0x3271, 'M', '라'),
    (0x3272, 'M', '마'),
    (0x3273, 'M', '바'),
    (0x3274, 'M', '사'),
    (0x3275, 'M', '아'),
    (0x3276, 'M', '자'),
    (0x3277, 'M', '차'),
    (0x3278, 'M', '카'),
    (0x3279, 'M', '타'),
    (0x327A, 'M', '파'),
    (0x327B, 'M', '하'),
    (0x327C, 'M', '참고'),
    (0x327D, 'M', '주의'),
    (0x327E, 'M', '우'),
    (0x327F, 'V'),
    (0x3280, 'M', '一'),
    (0x3281, 'M', '二'),
    (0x3282, 'M', '三'),
    (0x3283, 'M', '四'),
    (0x3284, 'M', '五'),
    (0x3285, 'M', '六'),
    (0x3286, 'M', '七'),
    (0x3287, 'M', '八'),
    (0x3288, 'M', '九'),
    (0x3289, 'M', '十'),
    (0x328A, 'M', '月'),
    (0x328B, 'M', '火'),
    (0x328C, 'M', '水'),
    (0x328D, 'M', '木'),
    (0x328E, 'M', '金'),
    (0x328F, 'M', '土'),
    (0x3290, 'M', '日'),
    (0x3291, 'M', '株'),
    (0x3292, 'M', '有'),
    (0x3293, 'M', '社'),
    (0x3294, 'M', '名'),
    (0x3295, 'M', '特'),
    (0x3296, 'M', '財'),
    (0x3297, 'M', '祝'),
    (0x3298, 'M', '労'),
    (0x3299, 'M', '秘'),
    (0x329A, 'M', '男'),
    (0x329B, 'M', '女'),
    (0x329C, 'M', '適'),
    (0x329D, 'M', '優'),
    (0x329E, 'M', '印'),
    (0x329F, 'M', '注'),
    (0x32A0, 'M', '項'),
    (0x32A1, 'M', '休'),
    (0x32A2, 'M', '写'),
    (0x32A3, 'M', '正'),
    (0x32A4, 'M', '上'),
    (0x32A5, 'M', '中'),
    (0x32A6, 'M', '下'),
    (0x32A7, 'M', '左'),
    (0x32A8, 'M', '右'),
    (0x32A9, 'M', '医'),
    (0x32AA, 'M', '宗'),
    (0x32AB, 'M', '学'),
    (0x32AC, 'M', '監'),
    (0x32AD, 'M', '企'),
    (0x32AE, 'M', '資'),
    (0x32AF, 'M', '協'),
    (0x32B0, 'M', '夜'),
    (0x32B1, 'M', '36'),
    (0x32B2, 'M', '37'),
    (0x32B3, 'M', '38'),
    (0x32B4, 'M', '39'),
    (0x32B5, 'M', '40'),
    ]

def _seg_32() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x32B6, 'M', '41'),
    (0x32B7, 'M', '42'),
    (0x32B8, 'M', '43'),
    (0x32B9, 'M', '44'),
    (0x32BA, 'M', '45'),
    (0x32BB, 'M', '46'),
    (0x32BC, 'M', '47'),
    (0x32BD, 'M', '48'),
    (0x32BE, 'M', '49'),
    (0x32BF, 'M', '50'),
    (0x32C0, 'M', '1月'),
    (0x32C1, 'M', '2月'),
    (0x32C2, 'M', '3月'),
    (0x32C3, 'M', '4月'),
    (0x32C4, 'M', '5月'),
    (0x32C5, 'M', '6月'),
    (0x32C6, 'M', '7月'),
    (0x32C7, 'M', '8月'),
    (0x32C8, 'M', '9月'),
    (0x32C9, 'M', '10月'),
    (0x32CA, 'M', '11月'),
    (0x32CB, 'M', '12月'),
    (0x32CC, 'M', 'hg'),
    (0x32CD, 'M', 'erg'),
    (0x32CE, 'M', 'ev'),
    (0x32CF, 'M', 'ltd'),
    (0x32D0, 'M', 'ア'),
    (0x32D1, 'M', 'イ'),
    (0x32D2, 'M', 'ウ'),
    (0x32D3, 'M', 'エ'),
    (0x32D4, 'M', 'オ'),
    (0x32D5, 'M', 'カ'),
    (0x32D6, 'M', 'キ'),
    (0x32D7, 'M', 'ク'),
    (0x32D8, 'M', 'ケ'),
    (0x32D9, 'M', 'コ'),
    (0x32DA, 'M', 'サ'),
    (0x32DB, 'M', 'シ'),
    (0x32DC, 'M', 'ス'),
    (0x32DD, 'M', 'セ'),
    (0x32DE, 'M', 'ソ'),
    (0x32DF, 'M', 'タ'),
    (0x32E0, 'M', 'チ'),
    (0x32E1, 'M', 'ツ'),
    (0x32E2, 'M', 'テ'),
    (0x32E3, 'M', 'ト'),
    (0x32E4, 'M', 'ナ'),
    (0x32E5, 'M', 'ニ'),
    (0x32E6, 'M', 'ヌ'),
    (0x32E7, 'M', 'ネ'),
    (0x32E8, 'M', 'ノ'),
    (0x32E9, 'M', 'ハ'),
    (0x32EA, 'M', 'ヒ'),
    (0x32EB, 'M', 'フ'),
    (0x32EC, 'M', 'ヘ'),
    (0x32ED, 'M', 'ホ'),
    (0x32EE, 'M', 'マ'),
    (0x32EF, 'M', 'ミ'),
    (0x32F0, 'M', 'ム'),
    (0x32F1, 'M', 'メ'),
    (0x32F2, 'M', 'モ'),
    (0x32F3, 'M', 'ヤ'),
    (0x32F4, 'M', 'ユ'),
    (0x32F5, 'M', 'ヨ'),
    (0x32F6, 'M', 'ラ'),
    (0x32F7, 'M', 'リ'),
    (0x32F8, 'M', 'ル'),
    (0x32F9, 'M', 'レ'),
    (0x32FA, 'M', 'ロ'),
    (0x32FB, 'M', 'ワ'),
    (0x32FC, 'M', 'ヰ'),
    (0x32FD, 'M', 'ヱ'),
    (0x32FE, 'M', 'ヲ'),
    (0x32FF, 'M', '令和'),
    (0x3300, 'M', 'アパート'),
    (0x3301, 'M', 'アルファ'),
    (0x3302, 'M', 'アンペア'),
    (0x3303, 'M', 'アール'),
    (0x3304, 'M', 'イニング'),
    (0x3305, 'M', 'インチ'),
    (0x3306, 'M', 'ウォン'),
    (0x3307, 'M', 'エスクード'),
    (0x3308, 'M', 'エーカー'),
    (0x3309, 'M', 'オンス'),
    (0x330A, 'M', 'オーム'),
    (0x330B, 'M', 'カイリ'),
    (0x330C, 'M', 'カラット'),
    (0x330D, 'M', 'カロリー'),
    (0x330E, 'M', 'ガロン'),
    (0x330F, 'M', 'ガンマ'),
    (0x3310, 'M', 'ギガ'),
    (0x3311, 'M', 'ギニー'),
    (0x3312, 'M', 'キュリー'),
    (0x3313, 'M', 'ギルダー'),
    (0x3314, 'M', 'キロ'),
    (0x3315, 'M', 'キログラム'),
    (0x3316, 'M', 'キロメートル'),
    (0x3317, 'M', 'キロワット'),
    (0x3318, 'M', 'グラム'),
    (0x3319, 'M', 'グラムトン'),
    ]

def _seg_33() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x331A, 'M', 'クルゼイロ'),
    (0x331B, 'M', 'クローネ'),
    (0x331C, 'M', 'ケース'),
    (0x331D, 'M', 'コルナ'),
    (0x331E, 'M', 'コーポ'),
    (0x331F, 'M', 'サイクル'),
    (0x3320, 'M', 'サンチーム'),
    (0x3321, 'M', 'シリング'),
    (0x3322, 'M', 'センチ'),
    (0x3323, 'M', 'セント'),
    (0x3324, 'M', 'ダース'),
    (0x3325, 'M', 'デシ'),
    (0x3326, 'M', 'ドル'),
    (0x3327, 'M', 'トン'),
    (0x3328, 'M', 'ナノ'),
    (0x3329, 'M', 'ノット'),
    (0x332A, 'M', 'ハイツ'),
    (0x332B, 'M', 'パーセント'),
    (0x332C, 'M', 'パーツ'),
    (0x332D, 'M', 'バーレル'),
    (0x332E, 'M', 'ピアストル'),
    (0x332F, 'M', 'ピクル'),
    (0x3330, 'M', 'ピコ'),
    (0x3331, 'M', 'ビル'),
    (0x3332, 'M', 'ファラッド'),
    (0x3333, 'M', 'フィート'),
    (0x3334, 'M', 'ブッシェル'),
    (0x3335, 'M', 'フラン'),
    (0x3336, 'M', 'ヘクタール'),
    (0x3337, 'M', 'ペソ'),
    (0x3338, 'M', 'ペニヒ'),
    (0x3339, 'M', 'ヘルツ'),
    (0x333A, 'M', 'ペンス'),
    (0x333B, 'M', 'ページ'),
    (0x333C, 'M', 'ベータ'),
    (0x333D, 'M', 'ポイント'),
    (0x333E, 'M', 'ボルト'),
    (0x333F, 'M', 'ホン'),
    (0x3340, 'M', 'ポンド'),
    (0x3341, 'M', 'ホール'),
    (0x3342, 'M', 'ホーン'),
    (0x3343, 'M', 'マイクロ'),
    (0x3344, 'M', 'マイル'),
    (0x3345, 'M', 'マッハ'),
    (0x3346, 'M', 'マルク'),
    (0x3347, 'M', 'マンション'),
    (0x3348, 'M', 'ミクロン'),
    (0x3349, 'M', 'ミリ'),
    (0x334A, 'M', 'ミリバール'),
    (0x334B, 'M', 'メガ'),
    (0x334C, 'M', 'メガトン'),
    (0x334D, 'M', 'メートル'),
    (0x334E, 'M', 'ヤード'),
    (0x334F, 'M', 'ヤール'),
    (0x3350, 'M', 'ユアン'),
    (0x3351, 'M', 'リットル'),
    (0x3352, 'M', 'リラ'),
    (0x3353, 'M', 'ルピー'),
    (0x3354, 'M', 'ルーブル'),
    (0x3355, 'M', 'レム'),
    (0x3356, 'M', 'レントゲン'),
    (0x3357, 'M', 'ワット'),
    (0x3358, 'M', '0点'),
    (0x3359, 'M', '1点'),
    (0x335A, 'M', '2点'),
    (0x335B, 'M', '3点'),
    (0x335C, 'M', '4点'),
    (0x335D, 'M', '5点'),
    (0x335E, 'M', '6点'),
    (0x335F, 'M', '7点'),
    (0x3360, 'M', '8点'),
    (0x3361, 'M', '9点'),
    (0x3362, 'M', '10点'),
    (0x3363, 'M', '11点'),
    (0x3364, 'M', '12点'),
    (0x3365, 'M', '13点'),
    (0x3366, 'M', '14点'),
    (0x3367, 'M', '15点'),
    (0x3368, 'M', '16点'),
    (0x3369, 'M', '17点'),
    (0x336A, 'M', '18点'),
    (0x336B, 'M', '19点'),
    (0x336C, 'M', '20点'),
    (0x336D, 'M', '21点'),
    (0x336E, 'M', '22点'),
    (0x336F, 'M', '23点'),
    (0x3370, 'M', '24点'),
    (0x3371, 'M', 'hpa'),
    (0x3372, 'M', 'da'),
    (0x3373, 'M', 'au'),
    (0x3374, 'M', 'bar'),
    (0x3375, 'M', 'ov'),
    (0x3376, 'M', 'pc'),
    (0x3377, 'M', 'dm'),
    (0x3378, 'M', 'dm2'),
    (0x3379, 'M', 'dm3'),
    (0x337A, 'M', 'iu'),
    (0x337B, 'M', '平成'),
    (0x337C, 'M', '昭和'),
    (0x337D, 'M', '大正'),
    ]

def _seg_34() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x337E, 'M', '明治'),
    (0x337F, 'M', '株式会社'),
    (0x3380, 'M', 'pa'),
    (0x3381, 'M', 'na'),
    (0x3382, 'M', 'μa'),
    (0x3383, 'M', 'ma'),
    (0x3384, 'M', 'ka'),
    (0x3385, 'M', 'kb'),
    (0x3386, 'M', 'mb'),
    (0x3387, 'M', 'gb'),
    (0x3388, 'M', 'cal'),
    (0x3389, 'M', 'kcal'),
    (0x338A, 'M', 'pf'),
    (0x338B, 'M', 'nf'),
    (0x338C, 'M', 'μf'),
    (0x338D, 'M', 'μg'),
    (0x338E, 'M', 'mg'),
    (0x338F, 'M', 'kg'),
    (0x3390, 'M', 'hz'),
    (0x3391, 'M', 'khz'),
    (0x3392, 'M', 'mhz'),
    (0x3393, 'M', 'ghz'),
    (0x3394, 'M', 'thz'),
    (0x3395, 'M', 'μl'),
    (0x3396, 'M', 'ml'),
    (0x3397, 'M', 'dl'),
    (0x3398, 'M', 'kl'),
    (0x3399, 'M', 'fm'),
    (0x339A, 'M', 'nm'),
    (0x339B, 'M', 'μm'),
    (0x339C, 'M', 'mm'),
    (0x339D, 'M', 'cm'),
    (0x339E, 'M', 'km'),
    (0x339F, 'M', 'mm2'),
    (0x33A0, 'M', 'cm2'),
    (0x33A1, 'M', 'm2'),
    (0x33A2, 'M', 'km2'),
    (0x33A3, 'M', 'mm3'),
    (0x33A4, 'M', 'cm3'),
    (0x33A5, 'M', 'm3'),
    (0x33A6, 'M', 'km3'),
    (0x33A7, 'M', 'm∕s'),
    (0x33A8, 'M', 'm∕s2'),
    (0x33A9, 'M', 'pa'),
    (0x33AA, 'M', 'kpa'),
    (0x33AB, 'M', 'mpa'),
    (0x33AC, 'M', 'gpa'),
    (0x33AD, 'M', 'rad'),
    (0x33AE, 'M', 'rad∕s'),
    (0x33AF, 'M', 'rad∕s2'),
    (0x33B0, 'M', 'ps'),
    (0x33B1, 'M', 'ns'),
    (0x33B2, 'M', 'μs'),
    (0x33B3, 'M', 'ms'),
    (0x33B4, 'M', 'pv'),
    (0x33B5, 'M', 'nv'),
    (0x33B6, 'M', 'μv'),
    (0x33B7, 'M', 'mv'),
    (0x33B8, 'M', 'kv'),
    (0x33B9, 'M', 'mv'),
    (0x33BA, 'M', 'pw'),
    (0x33BB, 'M', 'nw'),
    (0x33BC, 'M', 'μw'),
    (0x33BD, 'M', 'mw'),
    (0x33BE, 'M', 'kw'),
    (0x33BF, 'M', 'mw'),
    (0x33C0, 'M', 'kω'),
    (0x33C1, 'M', 'mω'),
    (0x33C2, 'X'),
    (0x33C3, 'M', 'bq'),
    (0x33C4, 'M', 'cc'),
    (0x33C5, 'M', 'cd'),
    (0x33C6, 'M', 'c∕kg'),
    (0x33C7, 'X'),
    (0x33C8, 'M', 'db'),
    (0x33C9, 'M', 'gy'),
    (0x33CA, 'M', 'ha'),
    (0x33CB, 'M', 'hp'),
    (0x33CC, 'M', 'in'),
    (0x33CD, 'M', 'kk'),
    (0x33CE, 'M', 'km'),
    (0x33CF, 'M', 'kt'),
    (0x33D0, 'M', 'lm'),
    (0x33D1, 'M', 'ln'),
    (0x33D2, 'M', 'log'),
    (0x33D3, 'M', 'lx'),
    (0x33D4, 'M', 'mb'),
    (0x33D5, 'M', 'mil'),
    (0x33D6, 'M', 'mol'),
    (0x33D7, 'M', 'ph'),
    (0x33D8, 'X'),
    (0x33D9, 'M', 'ppm'),
    (0x33DA, 'M', 'pr'),
    (0x33DB, 'M', 'sr'),
    (0x33DC, 'M', 'sv'),
    (0x33DD, 'M', 'wb'),
    (0x33DE, 'M', 'v∕m'),
    (0x33DF, 'M', 'a∕m'),
    (0x33E0, 'M', '1日'),
    (0x33E1, 'M', '2日'),
    ]

def _seg_35() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x33E2, 'M', '3日'),
    (0x33E3, 'M', '4日'),
    (0x33E4, 'M', '5日'),
    (0x33E5, 'M', '6日'),
    (0x33E6, 'M', '7日'),
    (0x33E7, 'M', '8日'),
    (0x33E8, 'M', '9日'),
    (0x33E9, 'M', '10日'),
    (0x33EA, 'M', '11日'),
    (0x33EB, 'M', '12日'),
    (0x33EC, 'M', '13日'),
    (0x33ED, 'M', '14日'),
    (0x33EE, 'M', '15日'),
    (0x33EF, 'M', '16日'),
    (0x33F0, 'M', '17日'),
    (0x33F1, 'M', '18日'),
    (0x33F2, 'M', '19日'),
    (0x33F3, 'M', '20日'),
    (0x33F4, 'M', '21日'),
    (0x33F5, 'M', '22日'),
    (0x33F6, 'M', '23日'),
    (0x33F7, 'M', '24日'),
    (0x33F8, 'M', '25日'),
    (0x33F9, 'M', '26日'),
    (0x33FA, 'M', '27日'),
    (0x33FB, 'M', '28日'),
    (0x33FC, 'M', '29日'),
    (0x33FD, 'M', '30日'),
    (0x33FE, 'M', '31日'),
    (0x33FF, 'M', 'gal'),
    (0x3400, 'V'),
    (0xA48D, 'X'),
    (0xA490, 'V'),
    (0xA4C7, 'X'),
    (0xA4D0, 'V'),
    (0xA62C, 'X'),
    (0xA640, 'M', 'ꙁ'),
    (0xA641, 'V'),
    (0xA642, 'M', 'ꙃ'),
    (0xA643, 'V'),
    (0xA644, 'M', 'ꙅ'),
    (0xA645, 'V'),
    (0xA646, 'M', 'ꙇ'),
    (0xA647, 'V'),
    (0xA648, 'M', 'ꙉ'),
    (0xA649, 'V'),
    (0xA64A, 'M', 'ꙋ'),
    (0xA64B, 'V'),
    (0xA64C, 'M', 'ꙍ'),
    (0xA64D, 'V'),
    (0xA64E, 'M', 'ꙏ'),
    (0xA64F, 'V'),
    (0xA650, 'M', 'ꙑ'),
    (0xA651, 'V'),
    (0xA652, 'M', 'ꙓ'),
    (0xA653, 'V'),
    (0xA654, 'M', 'ꙕ'),
    (0xA655, 'V'),
    (0xA656, 'M', 'ꙗ'),
    (0xA657, 'V'),
    (0xA658, 'M', 'ꙙ'),
    (0xA659, 'V'),
    (0xA65A, 'M', 'ꙛ'),
    (0xA65B, 'V'),
    (0xA65C, 'M', 'ꙝ'),
    (0xA65D, 'V'),
    (0xA65E, 'M', 'ꙟ'),
    (0xA65F, 'V'),
    (0xA660, 'M', 'ꙡ'),
    (0xA661, 'V'),
    (0xA662, 'M', 'ꙣ'),
    (0xA663, 'V'),
    (0xA664, 'M', 'ꙥ'),
    (0xA665, 'V'),
    (0xA666, 'M', 'ꙧ'),
    (0xA667, 'V'),
    (0xA668, 'M', 'ꙩ'),
    (0xA669, 'V'),
    (0xA66A, 'M', 'ꙫ'),
    (0xA66B, 'V'),
    (0xA66C, 'M', 'ꙭ'),
    (0xA66D, 'V'),
    (0xA680, 'M', 'ꚁ'),
    (0xA681, 'V'),
    (0xA682, 'M', 'ꚃ'),
    (0xA683, 'V'),
    (0xA684, 'M', 'ꚅ'),
    (0xA685, 'V'),
    (0xA686, 'M', 'ꚇ'),
    (0xA687, 'V'),
    (0xA688, 'M', 'ꚉ'),
    (0xA689, 'V'),
    (0xA68A, 'M', 'ꚋ'),
    (0xA68B, 'V'),
    (0xA68C, 'M', 'ꚍ'),
    (0xA68D, 'V'),
    (0xA68E, 'M', 'ꚏ'),
    (0xA68F, 'V'),
    (0xA690, 'M', 'ꚑ'),
    (0xA691, 'V'),
    ]

def _seg_36() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xA692, 'M', 'ꚓ'),
    (0xA693, 'V'),
    (0xA694, 'M', 'ꚕ'),
    (0xA695, 'V'),
    (0xA696, 'M', 'ꚗ'),
    (0xA697, 'V'),
    (0xA698, 'M', 'ꚙ'),
    (0xA699, 'V'),
    (0xA69A, 'M', 'ꚛ'),
    (0xA69B, 'V'),
    (0xA69C, 'M', 'ъ'),
    (0xA69D, 'M', 'ь'),
    (0xA69E, 'V'),
    (0xA6F8, 'X'),
    (0xA700, 'V'),
    (0xA722, 'M', 'ꜣ'),
    (0xA723, 'V'),
    (0xA724, 'M', 'ꜥ'),
    (0xA725, 'V'),
    (0xA726, 'M', 'ꜧ'),
    (0xA727, 'V'),
    (0xA728, 'M', 'ꜩ'),
    (0xA729, 'V'),
    (0xA72A, 'M', 'ꜫ'),
    (0xA72B, 'V'),
    (0xA72C, 'M', 'ꜭ'),
    (0xA72D, 'V'),
    (0xA72E, 'M', 'ꜯ'),
    (0xA72F, 'V'),
    (0xA732, 'M', 'ꜳ'),
    (0xA733, 'V'),
    (0xA734, 'M', 'ꜵ'),
    (0xA735, 'V'),
    (0xA736, 'M', 'ꜷ'),
    (0xA737, 'V'),
    (0xA738, 'M', 'ꜹ'),
    (0xA739, 'V'),
    (0xA73A, 'M', 'ꜻ'),
    (0xA73B, 'V'),
    (0xA73C, 'M', 'ꜽ'),
    (0xA73D, 'V'),
    (0xA73E, 'M', 'ꜿ'),
    (0xA73F, 'V'),
    (0xA740, 'M', 'ꝁ'),
    (0xA741, 'V'),
    (0xA742, 'M', 'ꝃ'),
    (0xA743, 'V'),
    (0xA744, 'M', 'ꝅ'),
    (0xA745, 'V'),
    (0xA746, 'M', 'ꝇ'),
    (0xA747, 'V'),
    (0xA748, 'M', 'ꝉ'),
    (0xA749, 'V'),
    (0xA74A, 'M', 'ꝋ'),
    (0xA74B, 'V'),
    (0xA74C, 'M', 'ꝍ'),
    (0xA74D, 'V'),
    (0xA74E, 'M', 'ꝏ'),
    (0xA74F, 'V'),
    (0xA750, 'M', 'ꝑ'),
    (0xA751, 'V'),
    (0xA752, 'M', 'ꝓ'),
    (0xA753, 'V'),
    (0xA754, 'M', 'ꝕ'),
    (0xA755, 'V'),
    (0xA756, 'M', 'ꝗ'),
    (0xA757, 'V'),
    (0xA758, 'M', 'ꝙ'),
    (0xA759, 'V'),
    (0xA75A, 'M', 'ꝛ'),
    (0xA75B, 'V'),
    (0xA75C, 'M', 'ꝝ'),
    (0xA75D, 'V'),
    (0xA75E, 'M', 'ꝟ'),
    (0xA75F, 'V'),
    (0xA760, 'M', 'ꝡ'),
    (0xA761, 'V'),
    (0xA762, 'M', 'ꝣ'),
    (0xA763, 'V'),
    (0xA764, 'M', 'ꝥ'),
    (0xA765, 'V'),
    (0xA766, 'M', 'ꝧ'),
    (0xA767, 'V'),
    (0xA768, 'M', 'ꝩ'),
    (0xA769, 'V'),
    (0xA76A, 'M', 'ꝫ'),
    (0xA76B, 'V'),
    (0xA76C, 'M', 'ꝭ'),
    (0xA76D, 'V'),
    (0xA76E, 'M', 'ꝯ'),
    (0xA76F, 'V'),
    (0xA770, 'M', 'ꝯ'),
    (0xA771, 'V'),
    (0xA779, 'M', 'ꝺ'),
    (0xA77A, 'V'),
    (0xA77B, 'M', 'ꝼ'),
    (0xA77C, 'V'),
    (0xA77D, 'M', 'ᵹ'),
    (0xA77E, 'M', 'ꝿ'),
    (0xA77F, 'V'),
    ]

def _seg_37() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xA780, 'M', 'ꞁ'),
    (0xA781, 'V'),
    (0xA782, 'M', 'ꞃ'),
    (0xA783, 'V'),
    (0xA784, 'M', 'ꞅ'),
    (0xA785, 'V'),
    (0xA786, 'M', 'ꞇ'),
    (0xA787, 'V'),
    (0xA78B, 'M', 'ꞌ'),
    (0xA78C, 'V'),
    (0xA78D, 'M', 'ɥ'),
    (0xA78E, 'V'),
    (0xA790, 'M', 'ꞑ'),
    (0xA791, 'V'),
    (0xA792, 'M', 'ꞓ'),
    (0xA793, 'V'),
    (0xA796, 'M', 'ꞗ'),
    (0xA797, 'V'),
    (0xA798, 'M', 'ꞙ'),
    (0xA799, 'V'),
    (0xA79A, 'M', 'ꞛ'),
    (0xA79B, 'V'),
    (0xA79C, 'M', 'ꞝ'),
    (0xA79D, 'V'),
    (0xA79E, 'M', 'ꞟ'),
    (0xA79F, 'V'),
    (0xA7A0, 'M', 'ꞡ'),
    (0xA7A1, 'V'),
    (0xA7A2, 'M', 'ꞣ'),
    (0xA7A3, 'V'),
    (0xA7A4, 'M', 'ꞥ'),
    (0xA7A5, 'V'),
    (0xA7A6, 'M', 'ꞧ'),
    (0xA7A7, 'V'),
    (0xA7A8, 'M', 'ꞩ'),
    (0xA7A9, 'V'),
    (0xA7AA, 'M', 'ɦ'),
    (0xA7AB, 'M', 'ɜ'),
    (0xA7AC, 'M', 'ɡ'),
    (0xA7AD, 'M', 'ɬ'),
    (0xA7AE, 'M', 'ɪ'),
    (0xA7AF, 'V'),
    (0xA7B0, 'M', 'ʞ'),
    (0xA7B1, 'M', 'ʇ'),
    (0xA7B2, 'M', 'ʝ'),
    (0xA7B3, 'M', 'ꭓ'),
    (0xA7B4, 'M', 'ꞵ'),
    (0xA7B5, 'V'),
    (0xA7B6, 'M', 'ꞷ'),
    (0xA7B7, 'V'),
    (0xA7B8, 'M', 'ꞹ'),
    (0xA7B9, 'V'),
    (0xA7BA, 'M', 'ꞻ'),
    (0xA7BB, 'V'),
    (0xA7BC, 'M', 'ꞽ'),
    (0xA7BD, 'V'),
    (0xA7BE, 'M', 'ꞿ'),
    (0xA7BF, 'V'),
    (0xA7C0, 'M', 'ꟁ'),
    (0xA7C1, 'V'),
    (0xA7C2, 'M', 'ꟃ'),
    (0xA7C3, 'V'),
    (0xA7C4, 'M', 'ꞔ'),
    (0xA7C5, 'M', 'ʂ'),
    (0xA7C6, 'M', 'ᶎ'),
    (0xA7C7, 'M', 'ꟈ'),
    (0xA7C8, 'V'),
    (0xA7C9, 'M', 'ꟊ'),
    (0xA7CA, 'V'),
    (0xA7CB, 'X'),
    (0xA7D0, 'M', 'ꟑ'),
    (0xA7D1, 'V'),
    (0xA7D2, 'X'),
    (0xA7D3, 'V'),
    (0xA7D4, 'X'),
    (0xA7D5, 'V'),
    (0xA7D6, 'M', 'ꟗ'),
    (0xA7D7, 'V'),
    (0xA7D8, 'M', 'ꟙ'),
    (0xA7D9, 'V'),
    (0xA7DA, 'X'),
    (0xA7F2, 'M', 'c'),
    (0xA7F3, 'M', 'f'),
    (0xA7F4, 'M', 'q'),
    (0xA7F5, 'M', 'ꟶ'),
    (0xA7F6, 'V'),
    (0xA7F8, 'M', 'ħ'),
    (0xA7F9, 'M', 'œ'),
    (0xA7FA, 'V'),
    (0xA82D, 'X'),
    (0xA830, 'V'),
    (0xA83A, 'X'),
    (0xA840, 'V'),
    (0xA878, 'X'),
    (0xA880, 'V'),
    (0xA8C6, 'X'),
    (0xA8CE, 'V'),
    (0xA8DA, 'X'),
    (0xA8E0, 'V'),
    (0xA954, 'X'),
    ]

def _seg_38() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xA95F, 'V'),
    (0xA97D, 'X'),
    (0xA980, 'V'),
    (0xA9CE, 'X'),
    (0xA9CF, 'V'),
    (0xA9DA, 'X'),
    (0xA9DE, 'V'),
    (0xA9FF, 'X'),
    (0xAA00, 'V'),
    (0xAA37, 'X'),
    (0xAA40, 'V'),
    (0xAA4E, 'X'),
    (0xAA50, 'V'),
    (0xAA5A, 'X'),
    (0xAA5C, 'V'),
    (0xAAC3, 'X'),
    (0xAADB, 'V'),
    (0xAAF7, 'X'),
    (0xAB01, 'V'),
    (0xAB07, 'X'),
    (0xAB09, 'V'),
    (0xAB0F, 'X'),
    (0xAB11, 'V'),
    (0xAB17, 'X'),
    (0xAB20, 'V'),
    (0xAB27, 'X'),
    (0xAB28, 'V'),
    (0xAB2F, 'X'),
    (0xAB30, 'V'),
    (0xAB5C, 'M', 'ꜧ'),
    (0xAB5D, 'M', 'ꬷ'),
    (0xAB5E, 'M', 'ɫ'),
    (0xAB5F, 'M', 'ꭒ'),
    (0xAB60, 'V'),
    (0xAB69, 'M', 'ʍ'),
    (0xAB6A, 'V'),
    (0xAB6C, 'X'),
    (0xAB70, 'M', 'Ꭰ'),
    (0xAB71, 'M', 'Ꭱ'),
    (0xAB72, 'M', 'Ꭲ'),
    (0xAB73, 'M', 'Ꭳ'),
    (0xAB74, 'M', 'Ꭴ'),
    (0xAB75, 'M', 'Ꭵ'),
    (0xAB76, 'M', 'Ꭶ'),
    (0xAB77, 'M', 'Ꭷ'),
    (0xAB78, 'M', 'Ꭸ'),
    (0xAB79, 'M', 'Ꭹ'),
    (0xAB7A, 'M', 'Ꭺ'),
    (0xAB7B, 'M', 'Ꭻ'),
    (0xAB7C, 'M', 'Ꭼ'),
    (0xAB7D, 'M', 'Ꭽ'),
    (0xAB7E, 'M', 'Ꭾ'),
    (0xAB7F, 'M', 'Ꭿ'),
    (0xAB80, 'M', 'Ꮀ'),
    (0xAB81, 'M', 'Ꮁ'),
    (0xAB82, 'M', 'Ꮂ'),
    (0xAB83, 'M', 'Ꮃ'),
    (0xAB84, 'M', 'Ꮄ'),
    (0xAB85, 'M', 'Ꮅ'),
    (0xAB86, 'M', 'Ꮆ'),
    (0xAB87, 'M', 'Ꮇ'),
    (0xAB88, 'M', 'Ꮈ'),
    (0xAB89, 'M', 'Ꮉ'),
    (0xAB8A, 'M', 'Ꮊ'),
    (0xAB8B, 'M', 'Ꮋ'),
    (0xAB8C, 'M', 'Ꮌ'),
    (0xAB8D, 'M', 'Ꮍ'),
    (0xAB8E, 'M', 'Ꮎ'),
    (0xAB8F, 'M', 'Ꮏ'),
    (0xAB90, 'M', 'Ꮐ'),
    (0xAB91, 'M', 'Ꮑ'),
    (0xAB92, 'M', 'Ꮒ'),
    (0xAB93, 'M', 'Ꮓ'),
    (0xAB94, 'M', 'Ꮔ'),
    (0xAB95, 'M', 'Ꮕ'),
    (0xAB96, 'M', 'Ꮖ'),
    (0xAB97, 'M', 'Ꮗ'),
    (0xAB98, 'M', 'Ꮘ'),
    (0xAB99, 'M', 'Ꮙ'),
    (0xAB9A, 'M', 'Ꮚ'),
    (0xAB9B, 'M', 'Ꮛ'),
    (0xAB9C, 'M', 'Ꮜ'),
    (0xAB9D, 'M', 'Ꮝ'),
    (0xAB9E, 'M', 'Ꮞ'),
    (0xAB9F, 'M', 'Ꮟ'),
    (0xABA0, 'M', 'Ꮠ'),
    (0xABA1, 'M', 'Ꮡ'),
    (0xABA2, 'M', 'Ꮢ'),
    (0xABA3, 'M', 'Ꮣ'),
    (0xABA4, 'M', 'Ꮤ'),
    (0xABA5, 'M', 'Ꮥ'),
    (0xABA6, 'M', 'Ꮦ'),
    (0xABA7, 'M', 'Ꮧ'),
    (0xABA8, 'M', 'Ꮨ'),
    (0xABA9, 'M', 'Ꮩ'),
    (0xABAA, 'M', 'Ꮪ'),
    (0xABAB, 'M', 'Ꮫ'),
    (0xABAC, 'M', 'Ꮬ'),
    (0xABAD, 'M', 'Ꮭ'),
    (0xABAE, 'M', 'Ꮮ'),
    ]

def _seg_39() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xABAF, 'M', 'Ꮯ'),
    (0xABB0, 'M', 'Ꮰ'),
    (0xABB1, 'M', 'Ꮱ'),
    (0xABB2, 'M', 'Ꮲ'),
    (0xABB3, 'M', 'Ꮳ'),
    (0xABB4, 'M', 'Ꮴ'),
    (0xABB5, 'M', 'Ꮵ'),
    (0xABB6, 'M', 'Ꮶ'),
    (0xABB7, 'M', 'Ꮷ'),
    (0xABB8, 'M', 'Ꮸ'),
    (0xABB9, 'M', 'Ꮹ'),
    (0xABBA, 'M', 'Ꮺ'),
    (0xABBB, 'M', 'Ꮻ'),
    (0xABBC, 'M', 'Ꮼ'),
    (0xABBD, 'M', 'Ꮽ'),
    (0xABBE, 'M', 'Ꮾ'),
    (0xABBF, 'M', 'Ꮿ'),
    (0xABC0, 'V'),
    (0xABEE, 'X'),
    (0xABF0, 'V'),
    (0xABFA, 'X'),
    (0xAC00, 'V'),
    (0xD7A4, 'X'),
    (0xD7B0, 'V'),
    (0xD7C7, 'X'),
    (0xD7CB, 'V'),
    (0xD7FC, 'X'),
    (0xF900, 'M', '豈'),
    (0xF901, 'M', '更'),
    (0xF902, 'M', '車'),
    (0xF903, 'M', '賈'),
    (0xF904, 'M', '滑'),
    (0xF905, 'M', '串'),
    (0xF906, 'M', '句'),
    (0xF907, 'M', '龜'),
    (0xF909, 'M', '契'),
    (0xF90A, 'M', '金'),
    (0xF90B, 'M', '喇'),
    (0xF90C, 'M', '奈'),
    (0xF90D, 'M', '懶'),
    (0xF90E, 'M', '癩'),
    (0xF90F, 'M', '羅'),
    (0xF910, 'M', '蘿'),
    (0xF911, 'M', '螺'),
    (0xF912, 'M', '裸'),
    (0xF913, 'M', '邏'),
    (0xF914, 'M', '樂'),
    (0xF915, 'M', '洛'),
    (0xF916, 'M', '烙'),
    (0xF917, 'M', '珞'),
    (0xF918, 'M', '落'),
    (0xF919, 'M', '酪'),
    (0xF91A, 'M', '駱'),
    (0xF91B, 'M', '亂'),
    (0xF91C, 'M', '卵'),
    (0xF91D, 'M', '欄'),
    (0xF91E, 'M', '爛'),
    (0xF91F, 'M', '蘭'),
    (0xF920, 'M', '鸞'),
    (0xF921, 'M', '嵐'),
    (0xF922, 'M', '濫'),
    (0xF923, 'M', '藍'),
    (0xF924, 'M', '襤'),
    (0xF925, 'M', '拉'),
    (0xF926, 'M', '臘'),
    (0xF927, 'M', '蠟'),
    (0xF928, 'M', '廊'),
    (0xF929, 'M', '朗'),
    (0xF92A, 'M', '浪'),
    (0xF92B, 'M', '狼'),
    (0xF92C, 'M', '郎'),
    (0xF92D, 'M', '來'),
    (0xF92E, 'M', '冷'),
    (0xF92F, 'M', '勞'),
    (0xF930, 'M', '擄'),
    (0xF931, 'M', '櫓'),
    (0xF932, 'M', '爐'),
    (0xF933, 'M', '盧'),
    (0xF934, 'M', '老'),
    (0xF935, 'M', '蘆'),
    (0xF936, 'M', '虜'),
    (0xF937, 'M', '路'),
    (0xF938, 'M', '露'),
    (0xF939, 'M', '魯'),
    (0xF93A, 'M', '鷺'),
    (0xF93B, 'M', '碌'),
    (0xF93C, 'M', '祿'),
    (0xF93D, 'M', '綠'),
    (0xF93E, 'M', '菉'),
    (0xF93F, 'M', '錄'),
    (0xF940, 'M', '鹿'),
    (0xF941, 'M', '論'),
    (0xF942, 'M', '壟'),
    (0xF943, 'M', '弄'),
    (0xF944, 'M', '籠'),
    (0xF945, 'M', '聾'),
    (0xF946, 'M', '牢'),
    (0xF947, 'M', '磊'),
    (0xF948, 'M', '賂'),
    (0xF949, 'M', '雷'),
    ]

def _seg_40() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xF94A, 'M', '壘'),
    (0xF94B, 'M', '屢'),
    (0xF94C, 'M', '樓'),
    (0xF94D, 'M', '淚'),
    (0xF94E, 'M', '漏'),
    (0xF94F, 'M', '累'),
    (0xF950, 'M', '縷'),
    (0xF951, 'M', '陋'),
    (0xF952, 'M', '勒'),
    (0xF953, 'M', '肋'),
    (0xF954, 'M', '凜'),
    (0xF955, 'M', '凌'),
    (0xF956, 'M', '稜'),
    (0xF957, 'M', '綾'),
    (0xF958, 'M', '菱'),
    (0xF959, 'M', '陵'),
    (0xF95A, 'M', '讀'),
    (0xF95B, 'M', '拏'),
    (0xF95C, 'M', '樂'),
    (0xF95D, 'M', '諾'),
    (0xF95E, 'M', '丹'),
    (0xF95F, 'M', '寧'),
    (0xF960, 'M', '怒'),
    (0xF961, 'M', '率'),
    (0xF962, 'M', '異'),
    (0xF963, 'M', '北'),
    (0xF964, 'M', '磻'),
    (0xF965, 'M', '便'),
    (0xF966, 'M', '復'),
    (0xF967, 'M', '不'),
    (0xF968, 'M', '泌'),
    (0xF969, 'M', '數'),
    (0xF96A, 'M', '索'),
    (0xF96B, 'M', '參'),
    (0xF96C, 'M', '塞'),
    (0xF96D, 'M', '省'),
    (0xF96E, 'M', '葉'),
    (0xF96F, 'M', '說'),
    (0xF970, 'M', '殺'),
    (0xF971, 'M', '辰'),
    (0xF972, 'M', '沈'),
    (0xF973, 'M', '拾'),
    (0xF974, 'M', '若'),
    (0xF975, 'M', '掠'),
    (0xF976, 'M', '略'),
    (0xF977, 'M', '亮'),
    (0xF978, 'M', '兩'),
    (0xF979, 'M', '凉'),
    (0xF97A, 'M', '梁'),
    (0xF97B, 'M', '糧'),
    (0xF97C, 'M', '良'),
    (0xF97D, 'M', '諒'),
    (0xF97E, 'M', '量'),
    (0xF97F, 'M', '勵'),
    (0xF980, 'M', '呂'),
    (0xF981, 'M', '女'),
    (0xF982, 'M', '廬'),
    (0xF983, 'M', '旅'),
    (0xF984, 'M', '濾'),
    (0xF985, 'M', '礪'),
    (0xF986, 'M', '閭'),
    (0xF987, 'M', '驪'),
    (0xF988, 'M', '麗'),
    (0xF989, 'M', '黎'),
    (0xF98A, 'M', '力'),
    (0xF98B, 'M', '曆'),
    (0xF98C, 'M', '歷'),
    (0xF98D, 'M', '轢'),
    (0xF98E, 'M', '年'),
    (0xF98F, 'M', '憐'),
    (0xF990, 'M', '戀'),
    (0xF991, 'M', '撚'),
    (0xF992, 'M', '漣'),
    (0xF993, 'M', '煉'),
    (0xF994, 'M', '璉'),
    (0xF995, 'M', '秊'),
    (0xF996, 'M', '練'),
    (0xF997, 'M', '聯'),
    (0xF998, 'M', '輦'),
    (0xF999, 'M', '蓮'),
    (0xF99A, 'M', '連'),
    (0xF99B, 'M', '鍊'),
    (0xF99C, 'M', '列'),
    (0xF99D, 'M', '劣'),
    (0xF99E, 'M', '咽'),
    (0xF99F, 'M', '烈'),
    (0xF9A0, 'M', '裂'),
    (0xF9A1, 'M', '說'),
    (0xF9A2, 'M', '廉'),
    (0xF9A3, 'M', '念'),
    (0xF9A4, 'M', '捻'),
    (0xF9A5, 'M', '殮'),
    (0xF9A6, 'M', '簾'),
    (0xF9A7, 'M', '獵'),
    (0xF9A8, 'M', '令'),
    (0xF9A9, 'M', '囹'),
    (0xF9AA, 'M', '寧'),
    (0xF9AB, 'M', '嶺'),
    (0xF9AC, 'M', '怜'),
    (0xF9AD, 'M', '玲'),
    ]

def _seg_41() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xF9AE, 'M', '瑩'),
    (0xF9AF, 'M', '羚'),
    (0xF9B0, 'M', '聆'),
    (0xF9B1, 'M', '鈴'),
    (0xF9B2, 'M', '零'),
    (0xF9B3, 'M', '靈'),
    (0xF9B4, 'M', '領'),
    (0xF9B5, 'M', '例'),
    (0xF9B6, 'M', '禮'),
    (0xF9B7, 'M', '醴'),
    (0xF9B8, 'M', '隸'),
    (0xF9B9, 'M', '惡'),
    (0xF9BA, 'M', '了'),
    (0xF9BB, 'M', '僚'),
    (0xF9BC, 'M', '寮'),
    (0xF9BD, 'M', '尿'),
    (0xF9BE, 'M', '料'),
    (0xF9BF, 'M', '樂'),
    (0xF9C0, 'M', '燎'),
    (0xF9C1, 'M', '療'),
    (0xF9C2, 'M', '蓼'),
    (0xF9C3, 'M', '遼'),
    (0xF9C4, 'M', '龍'),
    (0xF9C5, 'M', '暈'),
    (0xF9C6, 'M', '阮'),
    (0xF9C7, 'M', '劉'),
    (0xF9C8, 'M', '杻'),
    (0xF9C9, 'M', '柳'),
    (0xF9CA, 'M', '流'),
    (0xF9CB, 'M', '溜'),
    (0xF9CC, 'M', '琉'),
    (0xF9CD, 'M', '留'),
    (0xF9CE, 'M', '硫'),
    (0xF9CF, 'M', '紐'),
    (0xF9D0, 'M', '類'),
    (0xF9D1, 'M', '六'),
    (0xF9D2, 'M', '戮'),
    (0xF9D3, 'M', '陸'),
    (0xF9D4, 'M', '倫'),
    (0xF9D5, 'M', '崙'),
    (0xF9D6, 'M', '淪'),
    (0xF9D7, 'M', '輪'),
    (0xF9D8, 'M', '律'),
    (0xF9D9, 'M', '慄'),
    (0xF9DA, 'M', '栗'),
    (0xF9DB, 'M', '率'),
    (0xF9DC, 'M', '隆'),
    (0xF9DD, 'M', '利'),
    (0xF9DE, 'M', '吏'),
    (0xF9DF, 'M', '履'),
    (0xF9E0, 'M', '易'),
    (0xF9E1, 'M', '李'),
    (0xF9E2, 'M', '梨'),
    (0xF9E3, 'M', '泥'),
    (0xF9E4, 'M', '理'),
    (0xF9E5, 'M', '痢'),
    (0xF9E6, 'M', '罹'),
    (0xF9E7, 'M', '裏'),
    (0xF9E8, 'M', '裡'),
    (0xF9E9, 'M', '里'),
    (0xF9EA, 'M', '離'),
    (0xF9EB, 'M', '匿'),
    (0xF9EC, 'M', '溺'),
    (0xF9ED, 'M', '吝'),
    (0xF9EE, 'M', '燐'),
    (0xF9EF, 'M', '璘'),
    (0xF9F0, 'M', '藺'),
    (0xF9F1, 'M', '隣'),
    (0xF9F2, 'M', '鱗'),
    (0xF9F3, 'M', '麟'),
    (0xF9F4, 'M', '林'),
    (0xF9F5, 'M', '淋'),
    (0xF9F6, 'M', '臨'),
    (0xF9F7, 'M', '立'),
    (0xF9F8, 'M', '笠'),
    (0xF9F9, 'M', '粒'),
    (0xF9FA, 'M', '狀'),
    (0xF9FB, 'M', '炙'),
    (0xF9FC, 'M', '識'),
    (0xF9FD, 'M', '什'),
    (0xF9FE, 'M', '茶'),
    (0xF9FF, 'M', '刺'),
    (0xFA00, 'M', '切'),
    (0xFA01, 'M', '度'),
    (0xFA02, 'M', '拓'),
    (0xFA03, 'M', '糖'),
    (0xFA04, 'M', '宅'),
    (0xFA05, 'M', '洞'),
    (0xFA06, 'M', '暴'),
    (0xFA07, 'M', '輻'),
    (0xFA08, 'M', '行'),
    (0xFA09, 'M', '降'),
    (0xFA0A, 'M', '見'),
    (0xFA0B, 'M', '廓'),
    (0xFA0C, 'M', '兀'),
    (0xFA0D, 'M', '嗀'),
    (0xFA0E, 'V'),
    (0xFA10, 'M', '塚'),
    (0xFA11, 'V'),
    (0xFA12, 'M', '晴'),
    ]

def _seg_42() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xFA13, 'V'),
    (0xFA15, 'M', '凞'),
    (0xFA16, 'M', '猪'),
    (0xFA17, 'M', '益'),
    (0xFA18, 'M', '礼'),
    (0xFA19, 'M', '神'),
    (0xFA1A, 'M', '祥'),
    (0xFA1B, 'M', '福'),
    (0xFA1C, 'M', '靖'),
    (0xFA1D, 'M', '精'),
    (0xFA1E, 'M', '羽'),
    (0xFA1F, 'V'),
    (0xFA20, 'M', '蘒'),
    (0xFA21, 'V'),
    (0xFA22, 'M', '諸'),
    (0xFA23, 'V'),
    (0xFA25, 'M', '逸'),
    (0xFA26, 'M', '都'),
    (0xFA27, 'V'),
    (0xFA2A, 'M', '飯'),
    (0xFA2B, 'M', '飼'),
    (0xFA2C, 'M', '館'),
    (0xFA2D, 'M', '鶴'),
    (0xFA2E, 'M', '郞'),
    (0xFA2F, 'M', '隷'),
    (0xFA30, 'M', '侮'),
    (0xFA31, 'M', '僧'),
    (0xFA32, 'M', '免'),
    (0xFA33, 'M', '勉'),
    (0xFA34, 'M', '勤'),
    (0xFA35, 'M', '卑'),
    (0xFA36, 'M', '喝'),
    (0xFA37, 'M', '嘆'),
    (0xFA38, 'M', '器'),
    (0xFA39, 'M', '塀'),
    (0xFA3A, 'M', '墨'),
    (0xFA3B, 'M', '層'),
    (0xFA3C, 'M', '屮'),
    (0xFA3D, 'M', '悔'),
    (0xFA3E, 'M', '慨'),
    (0xFA3F, 'M', '憎'),
    (0xFA40, 'M', '懲'),
    (0xFA41, 'M', '敏'),
    (0xFA42, 'M', '既'),
    (0xFA43, 'M', '暑'),
    (0xFA44, 'M', '梅'),
    (0xFA45, 'M', '海'),
    (0xFA46, 'M', '渚'),
    (0xFA47, 'M', '漢'),
    (0xFA48, 'M', '煮'),
    (0xFA49, 'M', '爫'),
    (0xFA4A, 'M', '琢'),
    (0xFA4B, 'M', '碑'),
    (0xFA4C, 'M', '社'),
    (0xFA4D, 'M', '祉'),
    (0xFA4E, 'M', '祈'),
    (0xFA4F, 'M', '祐'),
    (0xFA50, 'M', '祖'),
    (0xFA51, 'M', '祝'),
    (0xFA52, 'M', '禍'),
    (0xFA53, 'M', '禎'),
    (0xFA54, 'M', '穀'),
    (0xFA55, 'M', '突'),
    (0xFA56, 'M', '節'),
    (0xFA57, 'M', '練'),
    (0xFA58, 'M', '縉'),
    (0xFA59, 'M', '繁'),
    (0xFA5A, 'M', '署'),
    (0xFA5B, 'M', '者'),
    (0xFA5C, 'M', '臭'),
    (0xFA5D, 'M', '艹'),
    (0xFA5F, 'M', '著'),
    (0xFA60, 'M', '褐'),
    (0xFA61, 'M', '視'),
    (0xFA62, 'M', '謁'),
    (0xFA63, 'M', '謹'),
    (0xFA64, 'M', '賓'),
    (0xFA65, 'M', '贈'),
    (0xFA66, 'M', '辶'),
    (0xFA67, 'M', '逸'),
    (0xFA68, 'M', '難'),
    (0xFA69, 'M', '響'),
    (0xFA6A, 'M', '頻'),
    (0xFA6B, 'M', '恵'),
    (0xFA6C, 'M', '𤋮'),
    (0xFA6D, 'M', '舘'),
    (0xFA6E, 'X'),
    (0xFA70, 'M', '並'),
    (0xFA71, 'M', '况'),
    (0xFA72, 'M', '全'),
    (0xFA73, 'M', '侀'),
    (0xFA74, 'M', '充'),
    (0xFA75, 'M', '冀'),
    (0xFA76, 'M', '勇'),
    (0xFA77, 'M', '勺'),
    (0xFA78, 'M', '喝'),
    (0xFA79, 'M', '啕'),
    (0xFA7A, 'M', '喙'),
    (0xFA7B, 'M', '嗢'),
    (0xFA7C, 'M', '塚'),
    ]

def _seg_43() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xFA7D, 'M', '墳'),
    (0xFA7E, 'M', '奄'),
    (0xFA7F, 'M', '奔'),
    (0xFA80, 'M', '婢'),
    (0xFA81, 'M', '嬨'),
    (0xFA82, 'M', '廒'),
    (0xFA83, 'M', '廙'),
    (0xFA84, 'M', '彩'),
    (0xFA85, 'M', '徭'),
    (0xFA86, 'M', '惘'),
    (0xFA87, 'M', '慎'),
    (0xFA88, 'M', '愈'),
    (0xFA89, 'M', '憎'),
    (0xFA8A, 'M', '慠'),
    (0xFA8B, 'M', '懲'),
    (0xFA8C, 'M', '戴'),
    (0xFA8D, 'M', '揄'),
    (0xFA8E, 'M', '搜'),
    (0xFA8F, 'M', '摒'),
    (0xFA90, 'M', '敖'),
    (0xFA91, 'M', '晴'),
    (0xFA92, 'M', '朗'),
    (0xFA93, 'M', '望'),
    (0xFA94, 'M', '杖'),
    (0xFA95, 'M', '歹'),
    (0xFA96, 'M', '殺'),
    (0xFA97, 'M', '流'),
    (0xFA98, 'M', '滛'),
    (0xFA99, 'M', '滋'),
    (0xFA9A, 'M', '漢'),
    (0xFA9B, 'M', '瀞'),
    (0xFA9C, 'M', '煮'),
    (0xFA9D, 'M', '瞧'),
    (0xFA9E, 'M', '爵'),
    (0xFA9F, 'M', '犯'),
    (0xFAA0, 'M', '猪'),
    (0xFAA1, 'M', '瑱'),
    (0xFAA2, 'M', '甆'),
    (0xFAA3, 'M', '画'),
    (0xFAA4, 'M', '瘝'),
    (0xFAA5, 'M', '瘟'),
    (0xFAA6, 'M', '益'),
    (0xFAA7, 'M', '盛'),
    (0xFAA8, 'M', '直'),
    (0xFAA9, 'M', '睊'),
    (0xFAAA, 'M', '着'),
    (0xFAAB, 'M', '磌'),
    (0xFAAC, 'M', '窱'),
    (0xFAAD, 'M', '節'),
    (0xFAAE, 'M', '类'),
    (0xFAAF, 'M', '絛'),
    (0xFAB0, 'M', '練'),
    (0xFAB1, 'M', '缾'),
    (0xFAB2, 'M', '者'),
    (0xFAB3, 'M', '荒'),
    (0xFAB4, 'M', '華'),
    (0xFAB5, 'M', '蝹'),
    (0xFAB6, 'M', '襁'),
    (0xFAB7, 'M', '覆'),
    (0xFAB8, 'M', '視'),
    (0xFAB9, 'M', '調'),
    (0xFABA, 'M', '諸'),
    (0xFABB, 'M', '請'),
    (0xFABC, 'M', '謁'),
    (0xFABD, 'M', '諾'),
    (0xFABE, 'M', '諭'),
    (0xFABF, 'M', '謹'),
    (0xFAC0, 'M', '變'),
    (0xFAC1, 'M', '贈'),
    (0xFAC2, 'M', '輸'),
    (0xFAC3, 'M', '遲'),
    (0xFAC4, 'M', '醙'),
    (0xFAC5, 'M', '鉶'),
    (0xFAC6, 'M', '陼'),
    (0xFAC7, 'M', '難'),
    (0xFAC8, 'M', '靖'),
    (0xFAC9, 'M', '韛'),
    (0xFACA, 'M', '響'),
    (0xFACB, 'M', '頋'),
    (0xFACC, 'M', '頻'),
    (0xFACD, 'M', '鬒'),
    (0xFACE, 'M', '龜'),
    (0xFACF, 'M', '𢡊'),
    (0xFAD0, 'M', '𢡄'),
    (0xFAD1, 'M', '𣏕'),
    (0xFAD2, 'M', '㮝'),
    (0xFAD3, 'M', '䀘'),
    (0xFAD4, 'M', '䀹'),
    (0xFAD5, 'M', '𥉉'),
    (0xFAD6, 'M', '𥳐'),
    (0xFAD7, 'M', '𧻓'),
    (0xFAD8, 'M', '齃'),
    (0xFAD9, 'M', '龎'),
    (0xFADA, 'X'),
    (0xFB00, 'M', 'ff'),
    (0xFB01, 'M', 'fi'),
    (0xFB02, 'M', 'fl'),
    (0xFB03, 'M', 'ffi'),
    (0xFB04, 'M', 'ffl'),
    (0xFB05, 'M', 'st'),
    ]

def _seg_44() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xFB07, 'X'),
    (0xFB13, 'M', 'մն'),
    (0xFB14, 'M', 'մե'),
    (0xFB15, 'M', 'մի'),
    (0xFB16, 'M', 'վն'),
    (0xFB17, 'M', 'մխ'),
    (0xFB18, 'X'),
    (0xFB1D, 'M', 'יִ'),
    (0xFB1E, 'V'),
    (0xFB1F, 'M', 'ײַ'),
    (0xFB20, 'M', 'ע'),
    (0xFB21, 'M', 'א'),
    (0xFB22, 'M', 'ד'),
    (0xFB23, 'M', 'ה'),
    (0xFB24, 'M', 'כ'),
    (0xFB25, 'M', 'ל'),
    (0xFB26, 'M', 'ם'),
    (0xFB27, 'M', 'ר'),
    (0xFB28, 'M', 'ת'),
    (0xFB29, '3', '+'),
    (0xFB2A, 'M', 'שׁ'),
    (0xFB2B, 'M', 'שׂ'),
    (0xFB2C, 'M', 'שּׁ'),
    (0xFB2D, 'M', 'שּׂ'),
    (0xFB2E, 'M', 'אַ'),
    (0xFB2F, 'M', 'אָ'),
    (0xFB30, 'M', 'אּ'),
    (0xFB31, 'M', 'בּ'),
    (0xFB32, 'M', 'גּ'),
    (0xFB33, 'M', 'דּ'),
    (0xFB34, 'M', 'הּ'),
    (0xFB35, 'M', 'וּ'),
    (0xFB36, 'M', 'זּ'),
    (0xFB37, 'X'),
    (0xFB38, 'M', 'טּ'),
    (0xFB39, 'M', 'יּ'),
    (0xFB3A, 'M', 'ךּ'),
    (0xFB3B, 'M', 'כּ'),
    (0xFB3C, 'M', 'לּ'),
    (0xFB3D, 'X'),
    (0xFB3E, 'M', 'מּ'),
    (0xFB3F, 'X'),
    (0xFB40, 'M', 'נּ'),
    (0xFB41, 'M', 'סּ'),
    (0xFB42, 'X'),
    (0xFB43, 'M', 'ףּ'),
    (0xFB44, 'M', 'פּ'),
    (0xFB45, 'X'),
    (0xFB46, 'M', 'צּ'),
    (0xFB47, 'M', 'קּ'),
    (0xFB48, 'M', 'רּ'),
    (0xFB49, 'M', 'שּ'),
    (0xFB4A, 'M', 'תּ'),
    (0xFB4B, 'M', 'וֹ'),
    (0xFB4C, 'M', 'בֿ'),
    (0xFB4D, 'M', 'כֿ'),
    (0xFB4E, 'M', 'פֿ'),
    (0xFB4F, 'M', 'אל'),
    (0xFB50, 'M', 'ٱ'),
    (0xFB52, 'M', 'ٻ'),
    (0xFB56, 'M', 'پ'),
    (0xFB5A, 'M', 'ڀ'),
    (0xFB5E, 'M', 'ٺ'),
    (0xFB62, 'M', 'ٿ'),
    (0xFB66, 'M', 'ٹ'),
    (0xFB6A, 'M', 'ڤ'),
    (0xFB6E, 'M', 'ڦ'),
    (0xFB72, 'M', 'ڄ'),
    (0xFB76, 'M', 'ڃ'),
    (0xFB7A, 'M', 'چ'),
    (0xFB7E, 'M', 'ڇ'),
    (0xFB82, 'M', 'ڍ'),
    (0xFB84, 'M', 'ڌ'),
    (0xFB86, 'M', 'ڎ'),
    (0xFB88, 'M', 'ڈ'),
    (0xFB8A, 'M', 'ژ'),
    (0xFB8C, 'M', 'ڑ'),
    (0xFB8E, 'M', 'ک'),
    (0xFB92, 'M', 'گ'),
    (0xFB96, 'M', 'ڳ'),
    (0xFB9A, 'M', 'ڱ'),
    (0xFB9E, 'M', 'ں'),
    (0xFBA0, 'M', 'ڻ'),
    (0xFBA4, 'M', 'ۀ'),
    (0xFBA6, 'M', 'ہ'),
    (0xFBAA, 'M', 'ھ'),
    (0xFBAE, 'M', 'ے'),
    (0xFBB0, 'M', 'ۓ'),
    (0xFBB2, 'V'),
    (0xFBC3, 'X'),
    (0xFBD3, 'M', 'ڭ'),
    (0xFBD7, 'M', 'ۇ'),
    (0xFBD9, 'M', 'ۆ'),
    (0xFBDB, 'M', 'ۈ'),
    (0xFBDD, 'M', 'ۇٴ'),
    (0xFBDE, 'M', 'ۋ'),
    (0xFBE0, 'M', 'ۅ'),
    (0xFBE2, 'M', 'ۉ'),
    (0xFBE4, 'M', 'ې'),
    (0xFBE8, 'M', 'ى'),
    ]

def _seg_45() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xFBEA, 'M', 'ئا'),
    (0xFBEC, 'M', 'ئە'),
    (0xFBEE, 'M', 'ئو'),
    (0xFBF0, 'M', 'ئۇ'),
    (0xFBF2, 'M', 'ئۆ'),
    (0xFBF4, 'M', 'ئۈ'),
    (0xFBF6, 'M', 'ئې'),
    (0xFBF9, 'M', 'ئى'),
    (0xFBFC, 'M', 'ی'),
    (0xFC00, 'M', 'ئج'),
    (0xFC01, 'M', 'ئح'),
    (0xFC02, 'M', 'ئم'),
    (0xFC03, 'M', 'ئى'),
    (0xFC04, 'M', 'ئي'),
    (0xFC05, 'M', 'بج'),
    (0xFC06, 'M', 'بح'),
    (0xFC07, 'M', 'بخ'),
    (0xFC08, 'M', 'بم'),
    (0xFC09, 'M', 'بى'),
    (0xFC0A, 'M', 'بي'),
    (0xFC0B, 'M', 'تج'),
    (0xFC0C, 'M', 'تح'),
    (0xFC0D, 'M', 'تخ'),
    (0xFC0E, 'M', 'تم'),
    (0xFC0F, 'M', 'تى'),
    (0xFC10, 'M', 'تي'),
    (0xFC11, 'M', 'ثج'),
    (0xFC12, 'M', 'ثم'),
    (0xFC13, 'M', 'ثى'),
    (0xFC14, 'M', 'ثي'),
    (0xFC15, 'M', 'جح'),
    (0xFC16, 'M', 'جم'),
    (0xFC17, 'M', 'حج'),
    (0xFC18, 'M', 'حم'),
    (0xFC19, 'M', 'خج'),
    (0xFC1A, 'M', 'خح'),
    (0xFC1B, 'M', 'خم'),
    (0xFC1C, 'M', 'سج'),
    (0xFC1D, 'M', 'سح'),
    (0xFC1E, 'M', 'سخ'),
    (0xFC1F, 'M', 'سم'),
    (0xFC20, 'M', 'صح'),
    (0xFC21, 'M', 'صم'),
    (0xFC22, 'M', 'ضج'),
    (0xFC23, 'M', 'ضح'),
    (0xFC24, 'M', 'ضخ'),
    (0xFC25, 'M', 'ضم'),
    (0xFC26, 'M', 'طح'),
    (0xFC27, 'M', 'طم'),
    (0xFC28, 'M', 'ظم'),
    (0xFC29, 'M', 'عج'),
    (0xFC2A, 'M', 'عم'),
    (0xFC2B, 'M', 'غج'),
    (0xFC2C, 'M', 'غم'),
    (0xFC2D, 'M', 'فج'),
    (0xFC2E, 'M', 'فح'),
    (0xFC2F, 'M', 'فخ'),
    (0xFC30, 'M', 'فم'),
    (0xFC31, 'M', 'فى'),
    (0xFC32, 'M', 'في'),
    (0xFC33, 'M', 'قح'),
    (0xFC34, 'M', 'قم'),
    (0xFC35, 'M', 'قى'),
    (0xFC36, 'M', 'قي'),
    (0xFC37, 'M', 'كا'),
    (0xFC38, 'M', 'كج'),
    (0xFC39, 'M', 'كح'),
    (0xFC3A, 'M', 'كخ'),
    (0xFC3B, 'M', 'كل'),
    (0xFC3C, 'M', 'كم'),
    (0xFC3D, 'M', 'كى'),
    (0xFC3E, 'M', 'كي'),
    (0xFC3F, 'M', 'لج'),
    (0xFC40, 'M', 'لح'),
    (0xFC41, 'M', 'لخ'),
    (0xFC42, 'M', 'لم'),
    (0xFC43, 'M', 'لى'),
    (0xFC44, 'M', 'لي'),
    (0xFC45, 'M', 'مج'),
    (0xFC46, 'M', 'مح'),
    (0xFC47, 'M', 'مخ'),
    (0xFC48, 'M', 'مم'),
    (0xFC49, 'M', 'مى'),
    (0xFC4A, 'M', 'مي'),
    (0xFC4B, 'M', 'نج'),
    (0xFC4C, 'M', 'نح'),
    (0xFC4D, 'M', 'نخ'),
    (0xFC4E, 'M', 'نم'),
    (0xFC4F, 'M', 'نى'),
    (0xFC50, 'M', 'ني'),
    (0xFC51, 'M', 'هج'),
    (0xFC52, 'M', 'هم'),
    (0xFC53, 'M', 'هى'),
    (0xFC54, 'M', 'هي'),
    (0xFC55, 'M', 'يج'),
    (0xFC56, 'M', 'يح'),
    (0xFC57, 'M', 'يخ'),
    (0xFC58, 'M', 'يم'),
    (0xFC59, 'M', 'يى'),
    (0xFC5A, 'M', 'يي'),
    ]

def _seg_46() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xFC5B, 'M', 'ذٰ'),
    (0xFC5C, 'M', 'رٰ'),
    (0xFC5D, 'M', 'ىٰ'),
    (0xFC5E, '3', ' ٌّ'),
    (0xFC5F, '3', ' ٍّ'),
    (0xFC60, '3', ' َّ'),
    (0xFC61, '3', ' ُّ'),
    (0xFC62, '3', ' ِّ'),
    (0xFC63, '3', ' ّٰ'),
    (0xFC64, 'M', 'ئر'),
    (0xFC65, 'M', 'ئز'),
    (0xFC66, 'M', 'ئم'),
    (0xFC67, 'M', 'ئن'),
    (0xFC68, 'M', 'ئى'),
    (0xFC69, 'M', 'ئي'),
    (0xFC6A, 'M', 'بر'),
    (0xFC6B, 'M', 'بز'),
    (0xFC6C, 'M', 'بم'),
    (0xFC6D, 'M', 'بن'),
    (0xFC6E, 'M', 'بى'),
    (0xFC6F, 'M', 'بي'),
    (0xFC70, 'M', 'تر'),
    (0xFC71, 'M', 'تز'),
    (0xFC72, 'M', 'تم'),
    (0xFC73, 'M', 'تن'),
    (0xFC74, 'M', 'تى'),
    (0xFC75, 'M', 'تي'),
    (0xFC76, 'M', 'ثر'),
    (0xFC77, 'M', 'ثز'),
    (0xFC78, 'M', 'ثم'),
    (0xFC79, 'M', 'ثن'),
    (0xFC7A, 'M', 'ثى'),
    (0xFC7B, 'M', 'ثي'),
    (0xFC7C, 'M', 'فى'),
    (0xFC7D, 'M', 'في'),
    (0xFC7E, 'M', 'قى'),
    (0xFC7F, 'M', 'قي'),
    (0xFC80, 'M', 'كا'),
    (0xFC81, 'M', 'كل'),
    (0xFC82, 'M', 'كم'),
    (0xFC83, 'M', 'كى'),
    (0xFC84, 'M', 'كي'),
    (0xFC85, 'M', 'لم'),
    (0xFC86, 'M', 'لى'),
    (0xFC87, 'M', 'لي'),
    (0xFC88, 'M', 'ما'),
    (0xFC89, 'M', 'مم'),
    (0xFC8A, 'M', 'نر'),
    (0xFC8B, 'M', 'نز'),
    (0xFC8C, 'M', 'نم'),
    (0xFC8D, 'M', 'نن'),
    (0xFC8E, 'M', 'نى'),
    (0xFC8F, 'M', 'ني'),
    (0xFC90, 'M', 'ىٰ'),
    (0xFC91, 'M', 'ير'),
    (0xFC92, 'M', 'يز'),
    (0xFC93, 'M', 'يم'),
    (0xFC94, 'M', 'ين'),
    (0xFC95, 'M', 'يى'),
    (0xFC96, 'M', 'يي'),
    (0xFC97, 'M', 'ئج'),
    (0xFC98, 'M', 'ئح'),
    (0xFC99, 'M', 'ئخ'),
    (0xFC9A, 'M', 'ئم'),
    (0xFC9B, 'M', 'ئه'),
    (0xFC9C, 'M', 'بج'),
    (0xFC9D, 'M', 'بح'),
    (0xFC9E, 'M', 'بخ'),
    (0xFC9F, 'M', 'بم'),
    (0xFCA0, 'M', 'به'),
    (0xFCA1, 'M', 'تج'),
    (0xFCA2, 'M', 'تح'),
    (0xFCA3, 'M', 'تخ'),
    (0xFCA4, 'M', 'تم'),
    (0xFCA5, 'M', 'ته'),
    (0xFCA6, 'M', 'ثم'),
    (0xFCA7, 'M', 'جح'),
    (0xFCA8, 'M', 'جم'),
    (0xFCA9, 'M', 'حج'),
    (0xFCAA, 'M', 'حم'),
    (0xFCAB, 'M', 'خج'),
    (0xFCAC, 'M', 'خم'),
    (0xFCAD, 'M', 'سج'),
    (0xFCAE, 'M', 'سح'),
    (0xFCAF, 'M', 'سخ'),
    (0xFCB0, 'M', 'سم'),
    (0xFCB1, 'M', 'صح'),
    (0xFCB2, 'M', 'صخ'),
    (0xFCB3, 'M', 'صم'),
    (0xFCB4, 'M', 'ضج'),
    (0xFCB5, 'M', 'ضح'),
    (0xFCB6, 'M', 'ضخ'),
    (0xFCB7, 'M', 'ضم'),
    (0xFCB8, 'M', 'طح'),
    (0xFCB9, 'M', 'ظم'),
    (0xFCBA, 'M', 'عج'),
    (0xFCBB, 'M', 'عم'),
    (0xFCBC, 'M', 'غج'),
    (0xFCBD, 'M', 'غم'),
    (0xFCBE, 'M', 'فج'),
    ]

def _seg_47() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xFCBF, 'M', 'فح'),
    (0xFCC0, 'M', 'فخ'),
    (0xFCC1, 'M', 'فم'),
    (0xFCC2, 'M', 'قح'),
    (0xFCC3, 'M', 'قم'),
    (0xFCC4, 'M', 'كج'),
    (0xFCC5, 'M', 'كح'),
    (0xFCC6, 'M', 'كخ'),
    (0xFCC7, 'M', 'كل'),
    (0xFCC8, 'M', 'كم'),
    (0xFCC9, 'M', 'لج'),
    (0xFCCA, 'M', 'لح'),
    (0xFCCB, 'M', 'لخ'),
    (0xFCCC, 'M', 'لم'),
    (0xFCCD, 'M', 'له'),
    (0xFCCE, 'M', 'مج'),
    (0xFCCF, 'M', 'مح'),
    (0xFCD0, 'M', 'مخ'),
    (0xFCD1, 'M', 'مم'),
    (0xFCD2, 'M', 'نج'),
    (0xFCD3, 'M', 'نح'),
    (0xFCD4, 'M', 'نخ'),
    (0xFCD5, 'M', 'نم'),
    (0xFCD6, 'M', 'نه'),
    (0xFCD7, 'M', 'هج'),
    (0xFCD8, 'M', 'هم'),
    (0xFCD9, 'M', 'هٰ'),
    (0xFCDA, 'M', 'يج'),
    (0xFCDB, 'M', 'يح'),
    (0xFCDC, 'M', 'يخ'),
    (0xFCDD, 'M', 'يم'),
    (0xFCDE, 'M', 'يه'),
    (0xFCDF, 'M', 'ئم'),
    (0xFCE0, 'M', 'ئه'),
    (0xFCE1, 'M', 'بم'),
    (0xFCE2, 'M', 'به'),
    (0xFCE3, 'M', 'تم'),
    (0xFCE4, 'M', 'ته'),
    (0xFCE5, 'M', 'ثم'),
    (0xFCE6, 'M', 'ثه'),
    (0xFCE7, 'M', 'سم'),
    (0xFCE8, 'M', 'سه'),
    (0xFCE9, 'M', 'شم'),
    (0xFCEA, 'M', 'شه'),
    (0xFCEB, 'M', 'كل'),
    (0xFCEC, 'M', 'كم'),
    (0xFCED, 'M', 'لم'),
    (0xFCEE, 'M', 'نم'),
    (0xFCEF, 'M', 'نه'),
    (0xFCF0, 'M', 'يم'),
    (0xFCF1, 'M', 'يه'),
    (0xFCF2, 'M', 'ـَّ'),
    (0xFCF3, 'M', 'ـُّ'),
    (0xFCF4, 'M', 'ـِّ'),
    (0xFCF5, 'M', 'طى'),
    (0xFCF6, 'M', 'طي'),
    (0xFCF7, 'M', 'عى'),
    (0xFCF8, 'M', 'عي'),
    (0xFCF9, 'M', 'غى'),
    (0xFCFA, 'M', 'غي'),
    (0xFCFB, 'M', 'سى'),
    (0xFCFC, 'M', 'سي'),
    (0xFCFD, 'M', 'شى'),
    (0xFCFE, 'M', 'شي'),
    (0xFCFF, 'M', 'حى'),
    (0xFD00, 'M', 'حي'),
    (0xFD01, 'M', 'جى'),
    (0xFD02, 'M', 'جي'),
    (0xFD03, 'M', 'خى'),
    (0xFD04, 'M', 'خي'),
    (0xFD05, 'M', 'صى'),
    (0xFD06, 'M', 'صي'),
    (0xFD07, 'M', 'ضى'),
    (0xFD08, 'M', 'ضي'),
    (0xFD09, 'M', 'شج'),
    (0xFD0A, 'M', 'شح'),
    (0xFD0B, 'M', 'شخ'),
    (0xFD0C, 'M', 'شم'),
    (0xFD0D, 'M', 'شر'),
    (0xFD0E, 'M', 'سر'),
    (0xFD0F, 'M', 'صر'),
    (0xFD10, 'M', 'ضر'),
    (0xFD11, 'M', 'طى'),
    (0xFD12, 'M', 'طي'),
    (0xFD13, 'M', 'عى'),
    (0xFD14, 'M', 'عي'),
    (0xFD15, 'M', 'غى'),
    (0xFD16, 'M', 'غي'),
    (0xFD17, 'M', 'سى'),
    (0xFD18, 'M', 'سي'),
    (0xFD19, 'M', 'شى'),
    (0xFD1A, 'M', 'شي'),
    (0xFD1B, 'M', 'حى'),
    (0xFD1C, 'M', 'حي'),
    (0xFD1D, 'M', 'جى'),
    (0xFD1E, 'M', 'جي'),
    (0xFD1F, 'M', 'خى'),
    (0xFD20, 'M', 'خي'),
    (0xFD21, 'M', 'صى'),
    (0xFD22, 'M', 'صي'),
    ]

def _seg_48() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xFD23, 'M', 'ضى'),
    (0xFD24, 'M', 'ضي'),
    (0xFD25, 'M', 'شج'),
    (0xFD26, 'M', 'شح'),
    (0xFD27, 'M', 'شخ'),
    (0xFD28, 'M', 'شم'),
    (0xFD29, 'M', 'شر'),
    (0xFD2A, 'M', 'سر'),
    (0xFD2B, 'M', 'صر'),
    (0xFD2C, 'M', 'ضر'),
    (0xFD2D, 'M', 'شج'),
    (0xFD2E, 'M', 'شح'),
    (0xFD2F, 'M', 'شخ'),
    (0xFD30, 'M', 'شم'),
    (0xFD31, 'M', 'سه'),
    (0xFD32, 'M', 'شه'),
    (0xFD33, 'M', 'طم'),
    (0xFD34, 'M', 'سج'),
    (0xFD35, 'M', 'سح'),
    (0xFD36, 'M', 'سخ'),
    (0xFD37, 'M', 'شج'),
    (0xFD38, 'M', 'شح'),
    (0xFD39, 'M', 'شخ'),
    (0xFD3A, 'M', 'طم'),
    (0xFD3B, 'M', 'ظم'),
    (0xFD3C, 'M', 'اً'),
    (0xFD3E, 'V'),
    (0xFD50, 'M', 'تجم'),
    (0xFD51, 'M', 'تحج'),
    (0xFD53, 'M', 'تحم'),
    (0xFD54, 'M', 'تخم'),
    (0xFD55, 'M', 'تمج'),
    (0xFD56, 'M', 'تمح'),
    (0xFD57, 'M', 'تمخ'),
    (0xFD58, 'M', 'جمح'),
    (0xFD5A, 'M', 'حمي'),
    (0xFD5B, 'M', 'حمى'),
    (0xFD5C, 'M', 'سحج'),
    (0xFD5D, 'M', 'سجح'),
    (0xFD5E, 'M', 'سجى'),
    (0xFD5F, 'M', 'سمح'),
    (0xFD61, 'M', 'سمج'),
    (0xFD62, 'M', 'سمم'),
    (0xFD64, 'M', 'صحح'),
    (0xFD66, 'M', 'صمم'),
    (0xFD67, 'M', 'شحم'),
    (0xFD69, 'M', 'شجي'),
    (0xFD6A, 'M', 'شمخ'),
    (0xFD6C, 'M', 'شمم'),
    (0xFD6E, 'M', 'ضحى'),
    (0xFD6F, 'M', 'ضخم'),
    (0xFD71, 'M', 'طمح'),
    (0xFD73, 'M', 'طمم'),
    (0xFD74, 'M', 'طمي'),
    (0xFD75, 'M', 'عجم'),
    (0xFD76, 'M', 'عمم'),
    (0xFD78, 'M', 'عمى'),
    (0xFD79, 'M', 'غمم'),
    (0xFD7A, 'M', 'غمي'),
    (0xFD7B, 'M', 'غمى'),
    (0xFD7C, 'M', 'فخم'),
    (0xFD7E, 'M', 'قمح'),
    (0xFD7F, 'M', 'قمم'),
    (0xFD80, 'M', 'لحم'),
    (0xFD81, 'M', 'لحي'),
    (0xFD82, 'M', 'لحى'),
    (0xFD83, 'M', 'لجج'),
    (0xFD85, 'M', 'لخم'),
    (0xFD87, 'M', 'لمح'),
    (0xFD89, 'M', 'محج'),
    (0xFD8A, 'M', 'محم'),
    (0xFD8B, 'M', 'محي'),
    (0xFD8C, 'M', 'مجح'),
    (0xFD8D, 'M', 'مجم'),
    (0xFD8E, 'M', 'مخج'),
    (0xFD8F, 'M', 'مخم'),
    (0xFD90, 'X'),
    (0xFD92, 'M', 'مجخ'),
    (0xFD93, 'M', 'همج'),
    (0xFD94, 'M', 'همم'),
    (0xFD95, 'M', 'نحم'),
    (0xFD96, 'M', 'نحى'),
    (0xFD97, 'M', 'نجم'),
    (0xFD99, 'M', 'نجى'),
    (0xFD9A, 'M', 'نمي'),
    (0xFD9B, 'M', 'نمى'),
    (0xFD9C, 'M', 'يمم'),
    (0xFD9E, 'M', 'بخي'),
    (0xFD9F, 'M', 'تجي'),
    (0xFDA0, 'M', 'تجى'),
    (0xFDA1, 'M', 'تخي'),
    (0xFDA2, 'M', 'تخى'),
    (0xFDA3, 'M', 'تمي'),
    (0xFDA4, 'M', 'تمى'),
    (0xFDA5, 'M', 'جمي'),
    (0xFDA6, 'M', 'جحى'),
    (0xFDA7, 'M', 'جمى'),
    (0xFDA8, 'M', 'سخى'),
    (0xFDA9, 'M', 'صحي'),
    (0xFDAA, 'M', 'شحي'),
    ]

def _seg_49() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xFDAB, 'M', 'ضحي'),
    (0xFDAC, 'M', 'لجي'),
    (0xFDAD, 'M', 'لمي'),
    (0xFDAE, 'M', 'يحي'),
    (0xFDAF, 'M', 'يجي'),
    (0xFDB0, 'M', 'يمي'),
    (0xFDB1, 'M', 'ممي'),
    (0xFDB2, 'M', 'قمي'),
    (0xFDB3, 'M', 'نحي'),
    (0xFDB4, 'M', 'قمح'),
    (0xFDB5, 'M', 'لحم'),
    (0xFDB6, 'M', 'عمي'),
    (0xFDB7, 'M', 'كمي'),
    (0xFDB8, 'M', 'نجح'),
    (0xFDB9, 'M', 'مخي'),
    (0xFDBA, 'M', 'لجم'),
    (0xFDBB, 'M', 'كمم'),
    (0xFDBC, 'M', 'لجم'),
    (0xFDBD, 'M', 'نجح'),
    (0xFDBE, 'M', 'جحي'),
    (0xFDBF, 'M', 'حجي'),
    (0xFDC0, 'M', 'مجي'),
    (0xFDC1, 'M', 'فمي'),
    (0xFDC2, 'M', 'بحي'),
    (0xFDC3, 'M', 'كمم'),
    (0xFDC4, 'M', 'عجم'),
    (0xFDC5, 'M', 'صمم'),
    (0xFDC6, 'M', 'سخي'),
    (0xFDC7, 'M', 'نجي'),
    (0xFDC8, 'X'),
    (0xFDCF, 'V'),
    (0xFDD0, 'X'),
    (0xFDF0, 'M', 'صلے'),
    (0xFDF1, 'M', 'قلے'),
    (0xFDF2, 'M', 'الله'),
    (0xFDF3, 'M', 'اكبر'),
    (0xFDF4, 'M', 'محمد'),
    (0xFDF5, 'M', 'صلعم'),
    (0xFDF6, 'M', 'رسول'),
    (0xFDF7, 'M', 'عليه'),
    (0xFDF8, 'M', 'وسلم'),
    (0xFDF9, 'M', 'صلى'),
    (0xFDFA, '3', 'صلى الله عليه وسلم'),
    (0xFDFB, '3', 'جل جلاله'),
    (0xFDFC, 'M', 'ریال'),
    (0xFDFD, 'V'),
    (0xFE00, 'I'),
    (0xFE10, '3', ','),
    (0xFE11, 'M', '、'),
    (0xFE12, 'X'),
    (0xFE13, '3', ':'),
    (0xFE14, '3', ';'),
    (0xFE15, '3', '!'),
    (0xFE16, '3', '?'),
    (0xFE17, 'M', '〖'),
    (0xFE18, 'M', '〗'),
    (0xFE19, 'X'),
    (0xFE20, 'V'),
    (0xFE30, 'X'),
    (0xFE31, 'M', '—'),
    (0xFE32, 'M', '–'),
    (0xFE33, '3', '_'),
    (0xFE35, '3', '('),
    (0xFE36, '3', ')'),
    (0xFE37, '3', '{'),
    (0xFE38, '3', '}'),
    (0xFE39, 'M', '〔'),
    (0xFE3A, 'M', '〕'),
    (0xFE3B, 'M', '【'),
    (0xFE3C, 'M', '】'),
    (0xFE3D, 'M', '《'),
    (0xFE3E, 'M', '》'),
    (0xFE3F, 'M', '〈'),
    (0xFE40, 'M', '〉'),
    (0xFE41, 'M', '「'),
    (0xFE42, 'M', '」'),
    (0xFE43, 'M', '『'),
    (0xFE44, 'M', '』'),
    (0xFE45, 'V'),
    (0xFE47, '3', '['),
    (0xFE48, '3', ']'),
    (0xFE49, '3', ' ̅'),
    (0xFE4D, '3', '_'),
    (0xFE50, '3', ','),
    (0xFE51, 'M', '、'),
    (0xFE52, 'X'),
    (0xFE54, '3', ';'),
    (0xFE55, '3', ':'),
    (0xFE56, '3', '?'),
    (0xFE57, '3', '!'),
    (0xFE58, 'M', '—'),
    (0xFE59, '3', '('),
    (0xFE5A, '3', ')'),
    (0xFE5B, '3', '{'),
    (0xFE5C, '3', '}'),
    (0xFE5D, 'M', '〔'),
    (0xFE5E, 'M', '〕'),
    (0xFE5F, '3', '#'),
    (0xFE60, '3', '&'),
    (0xFE61, '3', '*'),
    ]

def _seg_50() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xFE62, '3', '+'),
    (0xFE63, 'M', '-'),
    (0xFE64, '3', '<'),
    (0xFE65, '3', '>'),
    (0xFE66, '3', '='),
    (0xFE67, 'X'),
    (0xFE68, '3', '\\'),
    (0xFE69, '3', '$'),
    (0xFE6A, '3', '%'),
    (0xFE6B, '3', '@'),
    (0xFE6C, 'X'),
    (0xFE70, '3', ' ً'),
    (0xFE71, 'M', 'ـً'),
    (0xFE72, '3', ' ٌ'),
    (0xFE73, 'V'),
    (0xFE74, '3', ' ٍ'),
    (0xFE75, 'X'),
    (0xFE76, '3', ' َ'),
    (0xFE77, 'M', 'ـَ'),
    (0xFE78, '3', ' ُ'),
    (0xFE79, 'M', 'ـُ'),
    (0xFE7A, '3', ' ِ'),
    (0xFE7B, 'M', 'ـِ'),
    (0xFE7C, '3', ' ّ'),
    (0xFE7D, 'M', 'ـّ'),
    (0xFE7E, '3', ' ْ'),
    (0xFE7F, 'M', 'ـْ'),
    (0xFE80, 'M', 'ء'),
    (0xFE81, 'M', 'آ'),
    (0xFE83, 'M', 'أ'),
    (0xFE85, 'M', 'ؤ'),
    (0xFE87, 'M', 'إ'),
    (0xFE89, 'M', 'ئ'),
    (0xFE8D, 'M', 'ا'),
    (0xFE8F, 'M', 'ب'),
    (0xFE93, 'M', 'ة'),
    (0xFE95, 'M', 'ت'),
    (0xFE99, 'M', 'ث'),
    (0xFE9D, 'M', 'ج'),
    (0xFEA1, 'M', 'ح'),
    (0xFEA5, 'M', 'خ'),
    (0xFEA9, 'M', 'د'),
    (0xFEAB, 'M', 'ذ'),
    (0xFEAD, 'M', 'ر'),
    (0xFEAF, 'M', 'ز'),
    (0xFEB1, 'M', 'س'),
    (0xFEB5, 'M', 'ش'),
    (0xFEB9, 'M', 'ص'),
    (0xFEBD, 'M', 'ض'),
    (0xFEC1, 'M', 'ط'),
    (0xFEC5, 'M', 'ظ'),
    (0xFEC9, 'M', 'ع'),
    (0xFECD, 'M', 'غ'),
    (0xFED1, 'M', 'ف'),
    (0xFED5, 'M', 'ق'),
    (0xFED9, 'M', 'ك'),
    (0xFEDD, 'M', 'ل'),
    (0xFEE1, 'M', 'م'),
    (0xFEE5, 'M', 'ن'),
    (0xFEE9, 'M', 'ه'),
    (0xFEED, 'M', 'و'),
    (0xFEEF, 'M', 'ى'),
    (0xFEF1, 'M', 'ي'),
    (0xFEF5, 'M', 'لآ'),
    (0xFEF7, 'M', 'لأ'),
    (0xFEF9, 'M', 'لإ'),
    (0xFEFB, 'M', 'لا'),
    (0xFEFD, 'X'),
    (0xFEFF, 'I'),
    (0xFF00, 'X'),
    (0xFF01, '3', '!'),
    (0xFF02, '3', '"'),
    (0xFF03, '3', '#'),
    (0xFF04, '3', '$'),
    (0xFF05, '3', '%'),
    (0xFF06, '3', '&'),
    (0xFF07, '3', '\''),
    (0xFF08, '3', '('),
    (0xFF09, '3', ')'),
    (0xFF0A, '3', '*'),
    (0xFF0B, '3', '+'),
    (0xFF0C, '3', ','),
    (0xFF0D, 'M', '-'),
    (0xFF0E, 'M', '.'),
    (0xFF0F, '3', '/'),
    (0xFF10, 'M', '0'),
    (0xFF11, 'M', '1'),
    (0xFF12, 'M', '2'),
    (0xFF13, 'M', '3'),
    (0xFF14, 'M', '4'),
    (0xFF15, 'M', '5'),
    (0xFF16, 'M', '6'),
    (0xFF17, 'M', '7'),
    (0xFF18, 'M', '8'),
    (0xFF19, 'M', '9'),
    (0xFF1A, '3', ':'),
    (0xFF1B, '3', ';'),
    (0xFF1C, '3', '<'),
    (0xFF1D, '3', '='),
    (0xFF1E, '3', '>'),
    ]

def _seg_51() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xFF1F, '3', '?'),
    (0xFF20, '3', '@'),
    (0xFF21, 'M', 'a'),
    (0xFF22, 'M', 'b'),
    (0xFF23, 'M', 'c'),
    (0xFF24, 'M', 'd'),
    (0xFF25, 'M', 'e'),
    (0xFF26, 'M', 'f'),
    (0xFF27, 'M', 'g'),
    (0xFF28, 'M', 'h'),
    (0xFF29, 'M', 'i'),
    (0xFF2A, 'M', 'j'),
    (0xFF2B, 'M', 'k'),
    (0xFF2C, 'M', 'l'),
    (0xFF2D, 'M', 'm'),
    (0xFF2E, 'M', 'n'),
    (0xFF2F, 'M', 'o'),
    (0xFF30, 'M', 'p'),
    (0xFF31, 'M', 'q'),
    (0xFF32, 'M', 'r'),
    (0xFF33, 'M', 's'),
    (0xFF34, 'M', 't'),
    (0xFF35, 'M', 'u'),
    (0xFF36, 'M', 'v'),
    (0xFF37, 'M', 'w'),
    (0xFF38, 'M', 'x'),
    (0xFF39, 'M', 'y'),
    (0xFF3A, 'M', 'z'),
    (0xFF3B, '3', '['),
    (0xFF3C, '3', '\\'),
    (0xFF3D, '3', ']'),
    (0xFF3E, '3', '^'),
    (0xFF3F, '3', '_'),
    (0xFF40, '3', '`'),
    (0xFF41, 'M', 'a'),
    (0xFF42, 'M', 'b'),
    (0xFF43, 'M', 'c'),
    (0xFF44, 'M', 'd'),
    (0xFF45, 'M', 'e'),
    (0xFF46, 'M', 'f'),
    (0xFF47, 'M', 'g'),
    (0xFF48, 'M', 'h'),
    (0xFF49, 'M', 'i'),
    (0xFF4A, 'M', 'j'),
    (0xFF4B, 'M', 'k'),
    (0xFF4C, 'M', 'l'),
    (0xFF4D, 'M', 'm'),
    (0xFF4E, 'M', 'n'),
    (0xFF4F, 'M', 'o'),
    (0xFF50, 'M', 'p'),
    (0xFF51, 'M', 'q'),
    (0xFF52, 'M', 'r'),
    (0xFF53, 'M', 's'),
    (0xFF54, 'M', 't'),
    (0xFF55, 'M', 'u'),
    (0xFF56, 'M', 'v'),
    (0xFF57, 'M', 'w'),
    (0xFF58, 'M', 'x'),
    (0xFF59, 'M', 'y'),
    (0xFF5A, 'M', 'z'),
    (0xFF5B, '3', '{'),
    (0xFF5C, '3', '|'),
    (0xFF5D, '3', '}'),
    (0xFF5E, '3', '~'),
    (0xFF5F, 'M', '⦅'),
    (0xFF60, 'M', '⦆'),
    (0xFF61, 'M', '.'),
    (0xFF62, 'M', '「'),
    (0xFF63, 'M', '」'),
    (0xFF64, 'M', '、'),
    (0xFF65, 'M', '・'),
    (0xFF66, 'M', 'ヲ'),
    (0xFF67, 'M', 'ァ'),
    (0xFF68, 'M', 'ィ'),
    (0xFF69, 'M', 'ゥ'),
    (0xFF6A, 'M', 'ェ'),
    (0xFF6B, 'M', 'ォ'),
    (0xFF6C, 'M', 'ャ'),
    (0xFF6D, 'M', 'ュ'),
    (0xFF6E, 'M', 'ョ'),
    (0xFF6F, 'M', 'ッ'),
    (0xFF70, 'M', 'ー'),
    (0xFF71, 'M', 'ア'),
    (0xFF72, 'M', 'イ'),
    (0xFF73, 'M', 'ウ'),
    (0xFF74, 'M', 'エ'),
    (0xFF75, 'M', 'オ'),
    (0xFF76, 'M', 'カ'),
    (0xFF77, 'M', 'キ'),
    (0xFF78, 'M', 'ク'),
    (0xFF79, 'M', 'ケ'),
    (0xFF7A, 'M', 'コ'),
    (0xFF7B, 'M', 'サ'),
    (0xFF7C, 'M', 'シ'),
    (0xFF7D, 'M', 'ス'),
    (0xFF7E, 'M', 'セ'),
    (0xFF7F, 'M', 'ソ'),
    (0xFF80, 'M', 'タ'),
    (0xFF81, 'M', 'チ'),
    (0xFF82, 'M', 'ツ'),
    ]

def _seg_52() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xFF83, 'M', 'テ'),
    (0xFF84, 'M', 'ト'),
    (0xFF85, 'M', 'ナ'),
    (0xFF86, 'M', 'ニ'),
    (0xFF87, 'M', 'ヌ'),
    (0xFF88, 'M', 'ネ'),
    (0xFF89, 'M', 'ノ'),
    (0xFF8A, 'M', 'ハ'),
    (0xFF8B, 'M', 'ヒ'),
    (0xFF8C, 'M', 'フ'),
    (0xFF8D, 'M', 'ヘ'),
    (0xFF8E, 'M', 'ホ'),
    (0xFF8F, 'M', 'マ'),
    (0xFF90, 'M', 'ミ'),
    (0xFF91, 'M', 'ム'),
    (0xFF92, 'M', 'メ'),
    (0xFF93, 'M', 'モ'),
    (0xFF94, 'M', 'ヤ'),
    (0xFF95, 'M', 'ユ'),
    (0xFF96, 'M', 'ヨ'),
    (0xFF97, 'M', 'ラ'),
    (0xFF98, 'M', 'リ'),
    (0xFF99, 'M', 'ル'),
    (0xFF9A, 'M', 'レ'),
    (0xFF9B, 'M', 'ロ'),
    (0xFF9C, 'M', 'ワ'),
    (0xFF9D, 'M', 'ン'),
    (0xFF9E, 'M', '゙'),
    (0xFF9F, 'M', '゚'),
    (0xFFA0, 'X'),
    (0xFFA1, 'M', 'ᄀ'),
    (0xFFA2, 'M', 'ᄁ'),
    (0xFFA3, 'M', 'ᆪ'),
    (0xFFA4, 'M', 'ᄂ'),
    (0xFFA5, 'M', 'ᆬ'),
    (0xFFA6, 'M', 'ᆭ'),
    (0xFFA7, 'M', 'ᄃ'),
    (0xFFA8, 'M', 'ᄄ'),
    (0xFFA9, 'M', 'ᄅ'),
    (0xFFAA, 'M', 'ᆰ'),
    (0xFFAB, 'M', 'ᆱ'),
    (0xFFAC, 'M', 'ᆲ'),
    (0xFFAD, 'M', 'ᆳ'),
    (0xFFAE, 'M', 'ᆴ'),
    (0xFFAF, 'M', 'ᆵ'),
    (0xFFB0, 'M', 'ᄚ'),
    (0xFFB1, 'M', 'ᄆ'),
    (0xFFB2, 'M', 'ᄇ'),
    (0xFFB3, 'M', 'ᄈ'),
    (0xFFB4, 'M', 'ᄡ'),
    (0xFFB5, 'M', 'ᄉ'),
    (0xFFB6, 'M', 'ᄊ'),
    (0xFFB7, 'M', 'ᄋ'),
    (0xFFB8, 'M', 'ᄌ'),
    (0xFFB9, 'M', 'ᄍ'),
    (0xFFBA, 'M', 'ᄎ'),
    (0xFFBB, 'M', 'ᄏ'),
    (0xFFBC, 'M', 'ᄐ'),
    (0xFFBD, 'M', 'ᄑ'),
    (0xFFBE, 'M', 'ᄒ'),
    (0xFFBF, 'X'),
    (0xFFC2, 'M', 'ᅡ'),
    (0xFFC3, 'M', 'ᅢ'),
    (0xFFC4, 'M', 'ᅣ'),
    (0xFFC5, 'M', 'ᅤ'),
    (0xFFC6, 'M', 'ᅥ'),
    (0xFFC7, 'M', 'ᅦ'),
    (0xFFC8, 'X'),
    (0xFFCA, 'M', 'ᅧ'),
    (0xFFCB, 'M', 'ᅨ'),
    (0xFFCC, 'M', 'ᅩ'),
    (0xFFCD, 'M', 'ᅪ'),
    (0xFFCE, 'M', 'ᅫ'),
    (0xFFCF, 'M', 'ᅬ'),
    (0xFFD0, 'X'),
    (0xFFD2, 'M', 'ᅭ'),
    (0xFFD3, 'M', 'ᅮ'),
    (0xFFD4, 'M', 'ᅯ'),
    (0xFFD5, 'M', 'ᅰ'),
    (0xFFD6, 'M', 'ᅱ'),
    (0xFFD7, 'M', 'ᅲ'),
    (0xFFD8, 'X'),
    (0xFFDA, 'M', 'ᅳ'),
    (0xFFDB, 'M', 'ᅴ'),
    (0xFFDC, 'M', 'ᅵ'),
    (0xFFDD, 'X'),
    (0xFFE0, 'M', '¢'),
    (0xFFE1, 'M', '£'),
    (0xFFE2, 'M', '¬'),
    (0xFFE3, '3', ' ̄'),
    (0xFFE4, 'M', '¦'),
    (0xFFE5, 'M', '¥'),
    (0xFFE6, 'M', '₩'),
    (0xFFE7, 'X'),
    (0xFFE8, 'M', '│'),
    (0xFFE9, 'M', '←'),
    (0xFFEA, 'M', '↑'),
    (0xFFEB, 'M', '→'),
    (0xFFEC, 'M', '↓'),
    (0xFFED, 'M', '■'),
    ]

def _seg_53() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0xFFEE, 'M', '○'),
    (0xFFEF, 'X'),
    (0x10000, 'V'),
    (0x1000C, 'X'),
    (0x1000D, 'V'),
    (0x10027, 'X'),
    (0x10028, 'V'),
    (0x1003B, 'X'),
    (0x1003C, 'V'),
    (0x1003E, 'X'),
    (0x1003F, 'V'),
    (0x1004E, 'X'),
    (0x10050, 'V'),
    (0x1005E, 'X'),
    (0x10080, 'V'),
    (0x100FB, 'X'),
    (0x10100, 'V'),
    (0x10103, 'X'),
    (0x10107, 'V'),
    (0x10134, 'X'),
    (0x10137, 'V'),
    (0x1018F, 'X'),
    (0x10190, 'V'),
    (0x1019D, 'X'),
    (0x101A0, 'V'),
    (0x101A1, 'X'),
    (0x101D0, 'V'),
    (0x101FE, 'X'),
    (0x10280, 'V'),
    (0x1029D, 'X'),
    (0x102A0, 'V'),
    (0x102D1, 'X'),
    (0x102E0, 'V'),
    (0x102FC, 'X'),
    (0x10300, 'V'),
    (0x10324, 'X'),
    (0x1032D, 'V'),
    (0x1034B, 'X'),
    (0x10350, 'V'),
    (0x1037B, 'X'),
    (0x10380, 'V'),
    (0x1039E, 'X'),
    (0x1039F, 'V'),
    (0x103C4, 'X'),
    (0x103C8, 'V'),
    (0x103D6, 'X'),
    (0x10400, 'M', '𐐨'),
    (0x10401, 'M', '𐐩'),
    (0x10402, 'M', '𐐪'),
    (0x10403, 'M', '𐐫'),
    (0x10404, 'M', '𐐬'),
    (0x10405, 'M', '𐐭'),
    (0x10406, 'M', '𐐮'),
    (0x10407, 'M', '𐐯'),
    (0x10408, 'M', '𐐰'),
    (0x10409, 'M', '𐐱'),
    (0x1040A, 'M', '𐐲'),
    (0x1040B, 'M', '𐐳'),
    (0x1040C, 'M', '𐐴'),
    (0x1040D, 'M', '𐐵'),
    (0x1040E, 'M', '𐐶'),
    (0x1040F, 'M', '𐐷'),
    (0x10410, 'M', '𐐸'),
    (0x10411, 'M', '𐐹'),
    (0x10412, 'M', '𐐺'),
    (0x10413, 'M', '𐐻'),
    (0x10414, 'M', '𐐼'),
    (0x10415, 'M', '𐐽'),
    (0x10416, 'M', '𐐾'),
    (0x10417, 'M', '𐐿'),
    (0x10418, 'M', '𐑀'),
    (0x10419, 'M', '𐑁'),
    (0x1041A, 'M', '𐑂'),
    (0x1041B, 'M', '𐑃'),
    (0x1041C, 'M', '𐑄'),
    (0x1041D, 'M', '𐑅'),
    (0x1041E, 'M', '𐑆'),
    (0x1041F, 'M', '𐑇'),
    (0x10420, 'M', '𐑈'),
    (0x10421, 'M', '𐑉'),
    (0x10422, 'M', '𐑊'),
    (0x10423, 'M', '𐑋'),
    (0x10424, 'M', '𐑌'),
    (0x10425, 'M', '𐑍'),
    (0x10426, 'M', '𐑎'),
    (0x10427, 'M', '𐑏'),
    (0x10428, 'V'),
    (0x1049E, 'X'),
    (0x104A0, 'V'),
    (0x104AA, 'X'),
    (0x104B0, 'M', '𐓘'),
    (0x104B1, 'M', '𐓙'),
    (0x104B2, 'M', '𐓚'),
    (0x104B3, 'M', '𐓛'),
    (0x104B4, 'M', '𐓜'),
    (0x104B5, 'M', '𐓝'),
    (0x104B6, 'M', '𐓞'),
    (0x104B7, 'M', '𐓟'),
    (0x104B8, 'M', '𐓠'),
    (0x104B9, 'M', '𐓡'),
    ]

def _seg_54() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x104BA, 'M', '𐓢'),
    (0x104BB, 'M', '𐓣'),
    (0x104BC, 'M', '𐓤'),
    (0x104BD, 'M', '𐓥'),
    (0x104BE, 'M', '𐓦'),
    (0x104BF, 'M', '𐓧'),
    (0x104C0, 'M', '𐓨'),
    (0x104C1, 'M', '𐓩'),
    (0x104C2, 'M', '𐓪'),
    (0x104C3, 'M', '𐓫'),
    (0x104C4, 'M', '𐓬'),
    (0x104C5, 'M', '𐓭'),
    (0x104C6, 'M', '𐓮'),
    (0x104C7, 'M', '𐓯'),
    (0x104C8, 'M', '𐓰'),
    (0x104C9, 'M', '𐓱'),
    (0x104CA, 'M', '𐓲'),
    (0x104CB, 'M', '𐓳'),
    (0x104CC, 'M', '𐓴'),
    (0x104CD, 'M', '𐓵'),
    (0x104CE, 'M', '𐓶'),
    (0x104CF, 'M', '𐓷'),
    (0x104D0, 'M', '𐓸'),
    (0x104D1, 'M', '𐓹'),
    (0x104D2, 'M', '𐓺'),
    (0x104D3, 'M', '𐓻'),
    (0x104D4, 'X'),
    (0x104D8, 'V'),
    (0x104FC, 'X'),
    (0x10500, 'V'),
    (0x10528, 'X'),
    (0x10530, 'V'),
    (0x10564, 'X'),
    (0x1056F, 'V'),
    (0x10570, 'M', '𐖗'),
    (0x10571, 'M', '𐖘'),
    (0x10572, 'M', '𐖙'),
    (0x10573, 'M', '𐖚'),
    (0x10574, 'M', '𐖛'),
    (0x10575, 'M', '𐖜'),
    (0x10576, 'M', '𐖝'),
    (0x10577, 'M', '𐖞'),
    (0x10578, 'M', '𐖟'),
    (0x10579, 'M', '𐖠'),
    (0x1057A, 'M', '𐖡'),
    (0x1057B, 'X'),
    (0x1057C, 'M', '𐖣'),
    (0x1057D, 'M', '𐖤'),
    (0x1057E, 'M', '𐖥'),
    (0x1057F, 'M', '𐖦'),
    (0x10580, 'M', '𐖧'),
    (0x10581, 'M', '𐖨'),
    (0x10582, 'M', '𐖩'),
    (0x10583, 'M', '𐖪'),
    (0x10584, 'M', '𐖫'),
    (0x10585, 'M', '𐖬'),
    (0x10586, 'M', '𐖭'),
    (0x10587, 'M', '𐖮'),
    (0x10588, 'M', '𐖯'),
    (0x10589, 'M', '𐖰'),
    (0x1058A, 'M', '𐖱'),
    (0x1058B, 'X'),
    (0x1058C, 'M', '𐖳'),
    (0x1058D, 'M', '𐖴'),
    (0x1058E, 'M', '𐖵'),
    (0x1058F, 'M', '𐖶'),
    (0x10590, 'M', '𐖷'),
    (0x10591, 'M', '𐖸'),
    (0x10592, 'M', '𐖹'),
    (0x10593, 'X'),
    (0x10594, 'M', '𐖻'),
    (0x10595, 'M', '𐖼'),
    (0x10596, 'X'),
    (0x10597, 'V'),
    (0x105A2, 'X'),
    (0x105A3, 'V'),
    (0x105B2, 'X'),
    (0x105B3, 'V'),
    (0x105BA, 'X'),
    (0x105BB, 'V'),
    (0x105BD, 'X'),
    (0x10600, 'V'),
    (0x10737, 'X'),
    (0x10740, 'V'),
    (0x10756, 'X'),
    (0x10760, 'V'),
    (0x10768, 'X'),
    (0x10780, 'V'),
    (0x10781, 'M', 'ː'),
    (0x10782, 'M', 'ˑ'),
    (0x10783, 'M', 'æ'),
    (0x10784, 'M', 'ʙ'),
    (0x10785, 'M', 'ɓ'),
    (0x10786, 'X'),
    (0x10787, 'M', 'ʣ'),
    (0x10788, 'M', 'ꭦ'),
    (0x10789, 'M', 'ʥ'),
    (0x1078A, 'M', 'ʤ'),
    (0x1078B, 'M', 'ɖ'),
    (0x1078C, 'M', 'ɗ'),
    ]

def _seg_55() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1078D, 'M', 'ᶑ'),
    (0x1078E, 'M', 'ɘ'),
    (0x1078F, 'M', 'ɞ'),
    (0x10790, 'M', 'ʩ'),
    (0x10791, 'M', 'ɤ'),
    (0x10792, 'M', 'ɢ'),
    (0x10793, 'M', 'ɠ'),
    (0x10794, 'M', 'ʛ'),
    (0x10795, 'M', 'ħ'),
    (0x10796, 'M', 'ʜ'),
    (0x10797, 'M', 'ɧ'),
    (0x10798, 'M', 'ʄ'),
    (0x10799, 'M', 'ʪ'),
    (0x1079A, 'M', 'ʫ'),
    (0x1079B, 'M', 'ɬ'),
    (0x1079C, 'M', '𝼄'),
    (0x1079D, 'M', 'ꞎ'),
    (0x1079E, 'M', 'ɮ'),
    (0x1079F, 'M', '𝼅'),
    (0x107A0, 'M', 'ʎ'),
    (0x107A1, 'M', '𝼆'),
    (0x107A2, 'M', 'ø'),
    (0x107A3, 'M', 'ɶ'),
    (0x107A4, 'M', 'ɷ'),
    (0x107A5, 'M', 'q'),
    (0x107A6, 'M', 'ɺ'),
    (0x107A7, 'M', '𝼈'),
    (0x107A8, 'M', 'ɽ'),
    (0x107A9, 'M', 'ɾ'),
    (0x107AA, 'M', 'ʀ'),
    (0x107AB, 'M', 'ʨ'),
    (0x107AC, 'M', 'ʦ'),
    (0x107AD, 'M', 'ꭧ'),
    (0x107AE, 'M', 'ʧ'),
    (0x107AF, 'M', 'ʈ'),
    (0x107B0, 'M', 'ⱱ'),
    (0x107B1, 'X'),
    (0x107B2, 'M', 'ʏ'),
    (0x107B3, 'M', 'ʡ'),
    (0x107B4, 'M', 'ʢ'),
    (0x107B5, 'M', 'ʘ'),
    (0x107B6, 'M', 'ǀ'),
    (0x107B7, 'M', 'ǁ'),
    (0x107B8, 'M', 'ǂ'),
    (0x107B9, 'M', '𝼊'),
    (0x107BA, 'M', '𝼞'),
    (0x107BB, 'X'),
    (0x10800, 'V'),
    (0x10806, 'X'),
    (0x10808, 'V'),
    (0x10809, 'X'),
    (0x1080A, 'V'),
    (0x10836, 'X'),
    (0x10837, 'V'),
    (0x10839, 'X'),
    (0x1083C, 'V'),
    (0x1083D, 'X'),
    (0x1083F, 'V'),
    (0x10856, 'X'),
    (0x10857, 'V'),
    (0x1089F, 'X'),
    (0x108A7, 'V'),
    (0x108B0, 'X'),
    (0x108E0, 'V'),
    (0x108F3, 'X'),
    (0x108F4, 'V'),
    (0x108F6, 'X'),
    (0x108FB, 'V'),
    (0x1091C, 'X'),
    (0x1091F, 'V'),
    (0x1093A, 'X'),
    (0x1093F, 'V'),
    (0x10940, 'X'),
    (0x10980, 'V'),
    (0x109B8, 'X'),
    (0x109BC, 'V'),
    (0x109D0, 'X'),
    (0x109D2, 'V'),
    (0x10A04, 'X'),
    (0x10A05, 'V'),
    (0x10A07, 'X'),
    (0x10A0C, 'V'),
    (0x10A14, 'X'),
    (0x10A15, 'V'),
    (0x10A18, 'X'),
    (0x10A19, 'V'),
    (0x10A36, 'X'),
    (0x10A38, 'V'),
    (0x10A3B, 'X'),
    (0x10A3F, 'V'),
    (0x10A49, 'X'),
    (0x10A50, 'V'),
    (0x10A59, 'X'),
    (0x10A60, 'V'),
    (0x10AA0, 'X'),
    (0x10AC0, 'V'),
    (0x10AE7, 'X'),
    (0x10AEB, 'V'),
    (0x10AF7, 'X'),
    (0x10B00, 'V'),
    ]

def _seg_56() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x10B36, 'X'),
    (0x10B39, 'V'),
    (0x10B56, 'X'),
    (0x10B58, 'V'),
    (0x10B73, 'X'),
    (0x10B78, 'V'),
    (0x10B92, 'X'),
    (0x10B99, 'V'),
    (0x10B9D, 'X'),
    (0x10BA9, 'V'),
    (0x10BB0, 'X'),
    (0x10C00, 'V'),
    (0x10C49, 'X'),
    (0x10C80, 'M', '𐳀'),
    (0x10C81, 'M', '𐳁'),
    (0x10C82, 'M', '𐳂'),
    (0x10C83, 'M', '𐳃'),
    (0x10C84, 'M', '𐳄'),
    (0x10C85, 'M', '𐳅'),
    (0x10C86, 'M', '𐳆'),
    (0x10C87, 'M', '𐳇'),
    (0x10C88, 'M', '𐳈'),
    (0x10C89, 'M', '𐳉'),
    (0x10C8A, 'M', '𐳊'),
    (0x10C8B, 'M', '𐳋'),
    (0x10C8C, 'M', '𐳌'),
    (0x10C8D, 'M', '𐳍'),
    (0x10C8E, 'M', '𐳎'),
    (0x10C8F, 'M', '𐳏'),
    (0x10C90, 'M', '𐳐'),
    (0x10C91, 'M', '𐳑'),
    (0x10C92, 'M', '𐳒'),
    (0x10C93, 'M', '𐳓'),
    (0x10C94, 'M', '𐳔'),
    (0x10C95, 'M', '𐳕'),
    (0x10C96, 'M', '𐳖'),
    (0x10C97, 'M', '𐳗'),
    (0x10C98, 'M', '𐳘'),
    (0x10C99, 'M', '𐳙'),
    (0x10C9A, 'M', '𐳚'),
    (0x10C9B, 'M', '𐳛'),
    (0x10C9C, 'M', '𐳜'),
    (0x10C9D, 'M', '𐳝'),
    (0x10C9E, 'M', '𐳞'),
    (0x10C9F, 'M', '𐳟'),
    (0x10CA0, 'M', '𐳠'),
    (0x10CA1, 'M', '𐳡'),
    (0x10CA2, 'M', '𐳢'),
    (0x10CA3, 'M', '𐳣'),
    (0x10CA4, 'M', '𐳤'),
    (0x10CA5, 'M', '𐳥'),
    (0x10CA6, 'M', '𐳦'),
    (0x10CA7, 'M', '𐳧'),
    (0x10CA8, 'M', '𐳨'),
    (0x10CA9, 'M', '𐳩'),
    (0x10CAA, 'M', '𐳪'),
    (0x10CAB, 'M', '𐳫'),
    (0x10CAC, 'M', '𐳬'),
    (0x10CAD, 'M', '𐳭'),
    (0x10CAE, 'M', '𐳮'),
    (0x10CAF, 'M', '𐳯'),
    (0x10CB0, 'M', '𐳰'),
    (0x10CB1, 'M', '𐳱'),
    (0x10CB2, 'M', '𐳲'),
    (0x10CB3, 'X'),
    (0x10CC0, 'V'),
    (0x10CF3, 'X'),
    (0x10CFA, 'V'),
    (0x10D28, 'X'),
    (0x10D30, 'V'),
    (0x10D3A, 'X'),
    (0x10E60, 'V'),
    (0x10E7F, 'X'),
    (0x10E80, 'V'),
    (0x10EAA, 'X'),
    (0x10EAB, 'V'),
    (0x10EAE, 'X'),
    (0x10EB0, 'V'),
    (0x10EB2, 'X'),
    (0x10EFD, 'V'),
    (0x10F28, 'X'),
    (0x10F30, 'V'),
    (0x10F5A, 'X'),
    (0x10F70, 'V'),
    (0x10F8A, 'X'),
    (0x10FB0, 'V'),
    (0x10FCC, 'X'),
    (0x10FE0, 'V'),
    (0x10FF7, 'X'),
    (0x11000, 'V'),
    (0x1104E, 'X'),
    (0x11052, 'V'),
    (0x11076, 'X'),
    (0x1107F, 'V'),
    (0x110BD, 'X'),
    (0x110BE, 'V'),
    (0x110C3, 'X'),
    (0x110D0, 'V'),
    (0x110E9, 'X'),
    (0x110F0, 'V'),
    ]

def _seg_57() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x110FA, 'X'),
    (0x11100, 'V'),
    (0x11135, 'X'),
    (0x11136, 'V'),
    (0x11148, 'X'),
    (0x11150, 'V'),
    (0x11177, 'X'),
    (0x11180, 'V'),
    (0x111E0, 'X'),
    (0x111E1, 'V'),
    (0x111F5, 'X'),
    (0x11200, 'V'),
    (0x11212, 'X'),
    (0x11213, 'V'),
    (0x11242, 'X'),
    (0x11280, 'V'),
    (0x11287, 'X'),
    (0x11288, 'V'),
    (0x11289, 'X'),
    (0x1128A, 'V'),
    (0x1128E, 'X'),
    (0x1128F, 'V'),
    (0x1129E, 'X'),
    (0x1129F, 'V'),
    (0x112AA, 'X'),
    (0x112B0, 'V'),
    (0x112EB, 'X'),
    (0x112F0, 'V'),
    (0x112FA, 'X'),
    (0x11300, 'V'),
    (0x11304, 'X'),
    (0x11305, 'V'),
    (0x1130D, 'X'),
    (0x1130F, 'V'),
    (0x11311, 'X'),
    (0x11313, 'V'),
    (0x11329, 'X'),
    (0x1132A, 'V'),
    (0x11331, 'X'),
    (0x11332, 'V'),
    (0x11334, 'X'),
    (0x11335, 'V'),
    (0x1133A, 'X'),
    (0x1133B, 'V'),
    (0x11345, 'X'),
    (0x11347, 'V'),
    (0x11349, 'X'),
    (0x1134B, 'V'),
    (0x1134E, 'X'),
    (0x11350, 'V'),
    (0x11351, 'X'),
    (0x11357, 'V'),
    (0x11358, 'X'),
    (0x1135D, 'V'),
    (0x11364, 'X'),
    (0x11366, 'V'),
    (0x1136D, 'X'),
    (0x11370, 'V'),
    (0x11375, 'X'),
    (0x11400, 'V'),
    (0x1145C, 'X'),
    (0x1145D, 'V'),
    (0x11462, 'X'),
    (0x11480, 'V'),
    (0x114C8, 'X'),
    (0x114D0, 'V'),
    (0x114DA, 'X'),
    (0x11580, 'V'),
    (0x115B6, 'X'),
    (0x115B8, 'V'),
    (0x115DE, 'X'),
    (0x11600, 'V'),
    (0x11645, 'X'),
    (0x11650, 'V'),
    (0x1165A, 'X'),
    (0x11660, 'V'),
    (0x1166D, 'X'),
    (0x11680, 'V'),
    (0x116BA, 'X'),
    (0x116C0, 'V'),
    (0x116CA, 'X'),
    (0x11700, 'V'),
    (0x1171B, 'X'),
    (0x1171D, 'V'),
    (0x1172C, 'X'),
    (0x11730, 'V'),
    (0x11747, 'X'),
    (0x11800, 'V'),
    (0x1183C, 'X'),
    (0x118A0, 'M', '𑣀'),
    (0x118A1, 'M', '𑣁'),
    (0x118A2, 'M', '𑣂'),
    (0x118A3, 'M', '𑣃'),
    (0x118A4, 'M', '𑣄'),
    (0x118A5, 'M', '𑣅'),
    (0x118A6, 'M', '𑣆'),
    (0x118A7, 'M', '𑣇'),
    (0x118A8, 'M', '𑣈'),
    (0x118A9, 'M', '𑣉'),
    (0x118AA, 'M', '𑣊'),
    ]

def _seg_58() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x118AB, 'M', '𑣋'),
    (0x118AC, 'M', '𑣌'),
    (0x118AD, 'M', '𑣍'),
    (0x118AE, 'M', '𑣎'),
    (0x118AF, 'M', '𑣏'),
    (0x118B0, 'M', '𑣐'),
    (0x118B1, 'M', '𑣑'),
    (0x118B2, 'M', '𑣒'),
    (0x118B3, 'M', '𑣓'),
    (0x118B4, 'M', '𑣔'),
    (0x118B5, 'M', '𑣕'),
    (0x118B6, 'M', '𑣖'),
    (0x118B7, 'M', '𑣗'),
    (0x118B8, 'M', '𑣘'),
    (0x118B9, 'M', '𑣙'),
    (0x118BA, 'M', '𑣚'),
    (0x118BB, 'M', '𑣛'),
    (0x118BC, 'M', '𑣜'),
    (0x118BD, 'M', '𑣝'),
    (0x118BE, 'M', '𑣞'),
    (0x118BF, 'M', '𑣟'),
    (0x118C0, 'V'),
    (0x118F3, 'X'),
    (0x118FF, 'V'),
    (0x11907, 'X'),
    (0x11909, 'V'),
    (0x1190A, 'X'),
    (0x1190C, 'V'),
    (0x11914, 'X'),
    (0x11915, 'V'),
    (0x11917, 'X'),
    (0x11918, 'V'),
    (0x11936, 'X'),
    (0x11937, 'V'),
    (0x11939, 'X'),
    (0x1193B, 'V'),
    (0x11947, 'X'),
    (0x11950, 'V'),
    (0x1195A, 'X'),
    (0x119A0, 'V'),
    (0x119A8, 'X'),
    (0x119AA, 'V'),
    (0x119D8, 'X'),
    (0x119DA, 'V'),
    (0x119E5, 'X'),
    (0x11A00, 'V'),
    (0x11A48, 'X'),
    (0x11A50, 'V'),
    (0x11AA3, 'X'),
    (0x11AB0, 'V'),
    (0x11AF9, 'X'),
    (0x11B00, 'V'),
    (0x11B0A, 'X'),
    (0x11C00, 'V'),
    (0x11C09, 'X'),
    (0x11C0A, 'V'),
    (0x11C37, 'X'),
    (0x11C38, 'V'),
    (0x11C46, 'X'),
    (0x11C50, 'V'),
    (0x11C6D, 'X'),
    (0x11C70, 'V'),
    (0x11C90, 'X'),
    (0x11C92, 'V'),
    (0x11CA8, 'X'),
    (0x11CA9, 'V'),
    (0x11CB7, 'X'),
    (0x11D00, 'V'),
    (0x11D07, 'X'),
    (0x11D08, 'V'),
    (0x11D0A, 'X'),
    (0x11D0B, 'V'),
    (0x11D37, 'X'),
    (0x11D3A, 'V'),
    (0x11D3B, 'X'),
    (0x11D3C, 'V'),
    (0x11D3E, 'X'),
    (0x11D3F, 'V'),
    (0x11D48, 'X'),
    (0x11D50, 'V'),
    (0x11D5A, 'X'),
    (0x11D60, 'V'),
    (0x11D66, 'X'),
    (0x11D67, 'V'),
    (0x11D69, 'X'),
    (0x11D6A, 'V'),
    (0x11D8F, 'X'),
    (0x11D90, 'V'),
    (0x11D92, 'X'),
    (0x11D93, 'V'),
    (0x11D99, 'X'),
    (0x11DA0, 'V'),
    (0x11DAA, 'X'),
    (0x11EE0, 'V'),
    (0x11EF9, 'X'),
    (0x11F00, 'V'),
    (0x11F11, 'X'),
    (0x11F12, 'V'),
    (0x11F3B, 'X'),
    (0x11F3E, 'V'),
    ]

def _seg_59() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x11F5A, 'X'),
    (0x11FB0, 'V'),
    (0x11FB1, 'X'),
    (0x11FC0, 'V'),
    (0x11FF2, 'X'),
    (0x11FFF, 'V'),
    (0x1239A, 'X'),
    (0x12400, 'V'),
    (0x1246F, 'X'),
    (0x12470, 'V'),
    (0x12475, 'X'),
    (0x12480, 'V'),
    (0x12544, 'X'),
    (0x12F90, 'V'),
    (0x12FF3, 'X'),
    (0x13000, 'V'),
    (0x13430, 'X'),
    (0x13440, 'V'),
    (0x13456, 'X'),
    (0x14400, 'V'),
    (0x14647, 'X'),
    (0x16800, 'V'),
    (0x16A39, 'X'),
    (0x16A40, 'V'),
    (0x16A5F, 'X'),
    (0x16A60, 'V'),
    (0x16A6A, 'X'),
    (0x16A6E, 'V'),
    (0x16ABF, 'X'),
    (0x16AC0, 'V'),
    (0x16ACA, 'X'),
    (0x16AD0, 'V'),
    (0x16AEE, 'X'),
    (0x16AF0, 'V'),
    (0x16AF6, 'X'),
    (0x16B00, 'V'),
    (0x16B46, 'X'),
    (0x16B50, 'V'),
    (0x16B5A, 'X'),
    (0x16B5B, 'V'),
    (0x16B62, 'X'),
    (0x16B63, 'V'),
    (0x16B78, 'X'),
    (0x16B7D, 'V'),
    (0x16B90, 'X'),
    (0x16E40, 'M', '𖹠'),
    (0x16E41, 'M', '𖹡'),
    (0x16E42, 'M', '𖹢'),
    (0x16E43, 'M', '𖹣'),
    (0x16E44, 'M', '𖹤'),
    (0x16E45, 'M', '𖹥'),
    (0x16E46, 'M', '𖹦'),
    (0x16E47, 'M', '𖹧'),
    (0x16E48, 'M', '𖹨'),
    (0x16E49, 'M', '𖹩'),
    (0x16E4A, 'M', '𖹪'),
    (0x16E4B, 'M', '𖹫'),
    (0x16E4C, 'M', '𖹬'),
    (0x16E4D, 'M', '𖹭'),
    (0x16E4E, 'M', '𖹮'),
    (0x16E4F, 'M', '𖹯'),
    (0x16E50, 'M', '𖹰'),
    (0x16E51, 'M', '𖹱'),
    (0x16E52, 'M', '𖹲'),
    (0x16E53, 'M', '𖹳'),
    (0x16E54, 'M', '𖹴'),
    (0x16E55, 'M', '𖹵'),
    (0x16E56, 'M', '𖹶'),
    (0x16E57, 'M', '𖹷'),
    (0x16E58, 'M', '𖹸'),
    (0x16E59, 'M', '𖹹'),
    (0x16E5A, 'M', '𖹺'),
    (0x16E5B, 'M', '𖹻'),
    (0x16E5C, 'M', '𖹼'),
    (0x16E5D, 'M', '𖹽'),
    (0x16E5E, 'M', '𖹾'),
    (0x16E5F, 'M', '𖹿'),
    (0x16E60, 'V'),
    (0x16E9B, 'X'),
    (0x16F00, 'V'),
    (0x16F4B, 'X'),
    (0x16F4F, 'V'),
    (0x16F88, 'X'),
    (0x16F8F, 'V'),
    (0x16FA0, 'X'),
    (0x16FE0, 'V'),
    (0x16FE5, 'X'),
    (0x16FF0, 'V'),
    (0x16FF2, 'X'),
    (0x17000, 'V'),
    (0x187F8, 'X'),
    (0x18800, 'V'),
    (0x18CD6, 'X'),
    (0x18D00, 'V'),
    (0x18D09, 'X'),
    (0x1AFF0, 'V'),
    (0x1AFF4, 'X'),
    (0x1AFF5, 'V'),
    (0x1AFFC, 'X'),
    (0x1AFFD, 'V'),
    ]

def _seg_60() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1AFFF, 'X'),
    (0x1B000, 'V'),
    (0x1B123, 'X'),
    (0x1B132, 'V'),
    (0x1B133, 'X'),
    (0x1B150, 'V'),
    (0x1B153, 'X'),
    (0x1B155, 'V'),
    (0x1B156, 'X'),
    (0x1B164, 'V'),
    (0x1B168, 'X'),
    (0x1B170, 'V'),
    (0x1B2FC, 'X'),
    (0x1BC00, 'V'),
    (0x1BC6B, 'X'),
    (0x1BC70, 'V'),
    (0x1BC7D, 'X'),
    (0x1BC80, 'V'),
    (0x1BC89, 'X'),
    (0x1BC90, 'V'),
    (0x1BC9A, 'X'),
    (0x1BC9C, 'V'),
    (0x1BCA0, 'I'),
    (0x1BCA4, 'X'),
    (0x1CF00, 'V'),
    (0x1CF2E, 'X'),
    (0x1CF30, 'V'),
    (0x1CF47, 'X'),
    (0x1CF50, 'V'),
    (0x1CFC4, 'X'),
    (0x1D000, 'V'),
    (0x1D0F6, 'X'),
    (0x1D100, 'V'),
    (0x1D127, 'X'),
    (0x1D129, 'V'),
    (0x1D15E, 'M', '𝅗𝅥'),
    (0x1D15F, 'M', '𝅘𝅥'),
    (0x1D160, 'M', '𝅘𝅥𝅮'),
    (0x1D161, 'M', '𝅘𝅥𝅯'),
    (0x1D162, 'M', '𝅘𝅥𝅰'),
    (0x1D163, 'M', '𝅘𝅥𝅱'),
    (0x1D164, 'M', '𝅘𝅥𝅲'),
    (0x1D165, 'V'),
    (0x1D173, 'X'),
    (0x1D17B, 'V'),
    (0x1D1BB, 'M', '𝆹𝅥'),
    (0x1D1BC, 'M', '𝆺𝅥'),
    (0x1D1BD, 'M', '𝆹𝅥𝅮'),
    (0x1D1BE, 'M', '𝆺𝅥𝅮'),
    (0x1D1BF, 'M', '𝆹𝅥𝅯'),
    (0x1D1C0, 'M', '𝆺𝅥𝅯'),
    (0x1D1C1, 'V'),
    (0x1D1EB, 'X'),
    (0x1D200, 'V'),
    (0x1D246, 'X'),
    (0x1D2C0, 'V'),
    (0x1D2D4, 'X'),
    (0x1D2E0, 'V'),
    (0x1D2F4, 'X'),
    (0x1D300, 'V'),
    (0x1D357, 'X'),
    (0x1D360, 'V'),
    (0x1D379, 'X'),
    (0x1D400, 'M', 'a'),
    (0x1D401, 'M', 'b'),
    (0x1D402, 'M', 'c'),
    (0x1D403, 'M', 'd'),
    (0x1D404, 'M', 'e'),
    (0x1D405, 'M', 'f'),
    (0x1D406, 'M', 'g'),
    (0x1D407, 'M', 'h'),
    (0x1D408, 'M', 'i'),
    (0x1D409, 'M', 'j'),
    (0x1D40A, 'M', 'k'),
    (0x1D40B, 'M', 'l'),
    (0x1D40C, 'M', 'm'),
    (0x1D40D, 'M', 'n'),
    (0x1D40E, 'M', 'o'),
    (0x1D40F, 'M', 'p'),
    (0x1D410, 'M', 'q'),
    (0x1D411, 'M', 'r'),
    (0x1D412, 'M', 's'),
    (0x1D413, 'M', 't'),
    (0x1D414, 'M', 'u'),
    (0x1D415, 'M', 'v'),
    (0x1D416, 'M', 'w'),
    (0x1D417, 'M', 'x'),
    (0x1D418, 'M', 'y'),
    (0x1D419, 'M', 'z'),
    (0x1D41A, 'M', 'a'),
    (0x1D41B, 'M', 'b'),
    (0x1D41C, 'M', 'c'),
    (0x1D41D, 'M', 'd'),
    (0x1D41E, 'M', 'e'),
    (0x1D41F, 'M', 'f'),
    (0x1D420, 'M', 'g'),
    (0x1D421, 'M', 'h'),
    (0x1D422, 'M', 'i'),
    (0x1D423, 'M', 'j'),
    (0x1D424, 'M', 'k'),
    ]

def _seg_61() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1D425, 'M', 'l'),
    (0x1D426, 'M', 'm'),
    (0x1D427, 'M', 'n'),
    (0x1D428, 'M', 'o'),
    (0x1D429, 'M', 'p'),
    (0x1D42A, 'M', 'q'),
    (0x1D42B, 'M', 'r'),
    (0x1D42C, 'M', 's'),
    (0x1D42D, 'M', 't'),
    (0x1D42E, 'M', 'u'),
    (0x1D42F, 'M', 'v'),
    (0x1D430, 'M', 'w'),
    (0x1D431, 'M', 'x'),
    (0x1D432, 'M', 'y'),
    (0x1D433, 'M', 'z'),
    (0x1D434, 'M', 'a'),
    (0x1D435, 'M', 'b'),
    (0x1D436, 'M', 'c'),
    (0x1D437, 'M', 'd'),
    (0x1D438, 'M', 'e'),
    (0x1D439, 'M', 'f'),
    (0x1D43A, 'M', 'g'),
    (0x1D43B, 'M', 'h'),
    (0x1D43C, 'M', 'i'),
    (0x1D43D, 'M', 'j'),
    (0x1D43E, 'M', 'k'),
    (0x1D43F, 'M', 'l'),
    (0x1D440, 'M', 'm'),
    (0x1D441, 'M', 'n'),
    (0x1D442, 'M', 'o'),
    (0x1D443, 'M', 'p'),
    (0x1D444, 'M', 'q'),
    (0x1D445, 'M', 'r'),
    (0x1D446, 'M', 's'),
    (0x1D447, 'M', 't'),
    (0x1D448, 'M', 'u'),
    (0x1D449, 'M', 'v'),
    (0x1D44A, 'M', 'w'),
    (0x1D44B, 'M', 'x'),
    (0x1D44C, 'M', 'y'),
    (0x1D44D, 'M', 'z'),
    (0x1D44E, 'M', 'a'),
    (0x1D44F, 'M', 'b'),
    (0x1D450, 'M', 'c'),
    (0x1D451, 'M', 'd'),
    (0x1D452, 'M', 'e'),
    (0x1D453, 'M', 'f'),
    (0x1D454, 'M', 'g'),
    (0x1D455, 'X'),
    (0x1D456, 'M', 'i'),
    (0x1D457, 'M', 'j'),
    (0x1D458, 'M', 'k'),
    (0x1D459, 'M', 'l'),
    (0x1D45A, 'M', 'm'),
    (0x1D45B, 'M', 'n'),
    (0x1D45C, 'M', 'o'),
    (0x1D45D, 'M', 'p'),
    (0x1D45E, 'M', 'q'),
    (0x1D45F, 'M', 'r'),
    (0x1D460, 'M', 's'),
    (0x1D461, 'M', 't'),
    (0x1D462, 'M', 'u'),
    (0x1D463, 'M', 'v'),
    (0x1D464, 'M', 'w'),
    (0x1D465, 'M', 'x'),
    (0x1D466, 'M', 'y'),
    (0x1D467, 'M', 'z'),
    (0x1D468, 'M', 'a'),
    (0x1D469, 'M', 'b'),
    (0x1D46A, 'M', 'c'),
    (0x1D46B, 'M', 'd'),
    (0x1D46C, 'M', 'e'),
    (0x1D46D, 'M', 'f'),
    (0x1D46E, 'M', 'g'),
    (0x1D46F, 'M', 'h'),
    (0x1D470, 'M', 'i'),
    (0x1D471, 'M', 'j'),
    (0x1D472, 'M', 'k'),
    (0x1D473, 'M', 'l'),
    (0x1D474, 'M', 'm'),
    (0x1D475, 'M', 'n'),
    (0x1D476, 'M', 'o'),
    (0x1D477, 'M', 'p'),
    (0x1D478, 'M', 'q'),
    (0x1D479, 'M', 'r'),
    (0x1D47A, 'M', 's'),
    (0x1D47B, 'M', 't'),
    (0x1D47C, 'M', 'u'),
    (0x1D47D, 'M', 'v'),
    (0x1D47E, 'M', 'w'),
    (0x1D47F, 'M', 'x'),
    (0x1D480, 'M', 'y'),
    (0x1D481, 'M', 'z'),
    (0x1D482, 'M', 'a'),
    (0x1D483, 'M', 'b'),
    (0x1D484, 'M', 'c'),
    (0x1D485, 'M', 'd'),
    (0x1D486, 'M', 'e'),
    (0x1D487, 'M', 'f'),
    (0x1D488, 'M', 'g'),
    ]

def _seg_62() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1D489, 'M', 'h'),
    (0x1D48A, 'M', 'i'),
    (0x1D48B, 'M', 'j'),
    (0x1D48C, 'M', 'k'),
    (0x1D48D, 'M', 'l'),
    (0x1D48E, 'M', 'm'),
    (0x1D48F, 'M', 'n'),
    (0x1D490, 'M', 'o'),
    (0x1D491, 'M', 'p'),
    (0x1D492, 'M', 'q'),
    (0x1D493, 'M', 'r'),
    (0x1D494, 'M', 's'),
    (0x1D495, 'M', 't'),
    (0x1D496, 'M', 'u'),
    (0x1D497, 'M', 'v'),
    (0x1D498, 'M', 'w'),
    (0x1D499, 'M', 'x'),
    (0x1D49A, 'M', 'y'),
    (0x1D49B, 'M', 'z'),
    (0x1D49C, 'M', 'a'),
    (0x1D49D, 'X'),
    (0x1D49E, 'M', 'c'),
    (0x1D49F, 'M', 'd'),
    (0x1D4A0, 'X'),
    (0x1D4A2, 'M', 'g'),
    (0x1D4A3, 'X'),
    (0x1D4A5, 'M', 'j'),
    (0x1D4A6, 'M', 'k'),
    (0x1D4A7, 'X'),
    (0x1D4A9, 'M', 'n'),
    (0x1D4AA, 'M', 'o'),
    (0x1D4AB, 'M', 'p'),
    (0x1D4AC, 'M', 'q'),
    (0x1D4AD, 'X'),
    (0x1D4AE, 'M', 's'),
    (0x1D4AF, 'M', 't'),
    (0x1D4B0, 'M', 'u'),
    (0x1D4B1, 'M', 'v'),
    (0x1D4B2, 'M', 'w'),
    (0x1D4B3, 'M', 'x'),
    (0x1D4B4, 'M', 'y'),
    (0x1D4B5, 'M', 'z'),
    (0x1D4B6, 'M', 'a'),
    (0x1D4B7, 'M', 'b'),
    (0x1D4B8, 'M', 'c'),
    (0x1D4B9, 'M', 'd'),
    (0x1D4BA, 'X'),
    (0x1D4BB, 'M', 'f'),
    (0x1D4BC, 'X'),
    (0x1D4BD, 'M', 'h'),
    (0x1D4BE, 'M', 'i'),
    (0x1D4BF, 'M', 'j'),
    (0x1D4C0, 'M', 'k'),
    (0x1D4C1, 'M', 'l'),
    (0x1D4C2, 'M', 'm'),
    (0x1D4C3, 'M', 'n'),
    (0x1D4C4, 'X'),
    (0x1D4C5, 'M', 'p'),
    (0x1D4C6, 'M', 'q'),
    (0x1D4C7, 'M', 'r'),
    (0x1D4C8, 'M', 's'),
    (0x1D4C9, 'M', 't'),
    (0x1D4CA, 'M', 'u'),
    (0x1D4CB, 'M', 'v'),
    (0x1D4CC, 'M', 'w'),
    (0x1D4CD, 'M', 'x'),
    (0x1D4CE, 'M', 'y'),
    (0x1D4CF, 'M', 'z'),
    (0x1D4D0, 'M', 'a'),
    (0x1D4D1, 'M', 'b'),
    (0x1D4D2, 'M', 'c'),
    (0x1D4D3, 'M', 'd'),
    (0x1D4D4, 'M', 'e'),
    (0x1D4D5, 'M', 'f'),
    (0x1D4D6, 'M', 'g'),
    (0x1D4D7, 'M', 'h'),
    (0x1D4D8, 'M', 'i'),
    (0x1D4D9, 'M', 'j'),
    (0x1D4DA, 'M', 'k'),
    (0x1D4DB, 'M', 'l'),
    (0x1D4DC, 'M', 'm'),
    (0x1D4DD, 'M', 'n'),
    (0x1D4DE, 'M', 'o'),
    (0x1D4DF, 'M', 'p'),
    (0x1D4E0, 'M', 'q'),
    (0x1D4E1, 'M', 'r'),
    (0x1D4E2, 'M', 's'),
    (0x1D4E3, 'M', 't'),
    (0x1D4E4, 'M', 'u'),
    (0x1D4E5, 'M', 'v'),
    (0x1D4E6, 'M', 'w'),
    (0x1D4E7, 'M', 'x'),
    (0x1D4E8, 'M', 'y'),
    (0x1D4E9, 'M', 'z'),
    (0x1D4EA, 'M', 'a'),
    (0x1D4EB, 'M', 'b'),
    (0x1D4EC, 'M', 'c'),
    (0x1D4ED, 'M', 'd'),
    (0x1D4EE, 'M', 'e'),
    (0x1D4EF, 'M', 'f'),
    ]

def _seg_63() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1D4F0, 'M', 'g'),
    (0x1D4F1, 'M', 'h'),
    (0x1D4F2, 'M', 'i'),
    (0x1D4F3, 'M', 'j'),
    (0x1D4F4, 'M', 'k'),
    (0x1D4F5, 'M', 'l'),
    (0x1D4F6, 'M', 'm'),
    (0x1D4F7, 'M', 'n'),
    (0x1D4F8, 'M', 'o'),
    (0x1D4F9, 'M', 'p'),
    (0x1D4FA, 'M', 'q'),
    (0x1D4FB, 'M', 'r'),
    (0x1D4FC, 'M', 's'),
    (0x1D4FD, 'M', 't'),
    (0x1D4FE, 'M', 'u'),
    (0x1D4FF, 'M', 'v'),
    (0x1D500, 'M', 'w'),
    (0x1D501, 'M', 'x'),
    (0x1D502, 'M', 'y'),
    (0x1D503, 'M', 'z'),
    (0x1D504, 'M', 'a'),
    (0x1D505, 'M', 'b'),
    (0x1D506, 'X'),
    (0x1D507, 'M', 'd'),
    (0x1D508, 'M', 'e'),
    (0x1D509, 'M', 'f'),
    (0x1D50A, 'M', 'g'),
    (0x1D50B, 'X'),
    (0x1D50D, 'M', 'j'),
    (0x1D50E, 'M', 'k'),
    (0x1D50F, 'M', 'l'),
    (0x1D510, 'M', 'm'),
    (0x1D511, 'M', 'n'),
    (0x1D512, 'M', 'o'),
    (0x1D513, 'M', 'p'),
    (0x1D514, 'M', 'q'),
    (0x1D515, 'X'),
    (0x1D516, 'M', 's'),
    (0x1D517, 'M', 't'),
    (0x1D518, 'M', 'u'),
    (0x1D519, 'M', 'v'),
    (0x1D51A, 'M', 'w'),
    (0x1D51B, 'M', 'x'),
    (0x1D51C, 'M', 'y'),
    (0x1D51D, 'X'),
    (0x1D51E, 'M', 'a'),
    (0x1D51F, 'M', 'b'),
    (0x1D520, 'M', 'c'),
    (0x1D521, 'M', 'd'),
    (0x1D522, 'M', 'e'),
    (0x1D523, 'M', 'f'),
    (0x1D524, 'M', 'g'),
    (0x1D525, 'M', 'h'),
    (0x1D526, 'M', 'i'),
    (0x1D527, 'M', 'j'),
    (0x1D528, 'M', 'k'),
    (0x1D529, 'M', 'l'),
    (0x1D52A, 'M', 'm'),
    (0x1D52B, 'M', 'n'),
    (0x1D52C, 'M', 'o'),
    (0x1D52D, 'M', 'p'),
    (0x1D52E, 'M', 'q'),
    (0x1D52F, 'M', 'r'),
    (0x1D530, 'M', 's'),
    (0x1D531, 'M', 't'),
    (0x1D532, 'M', 'u'),
    (0x1D533, 'M', 'v'),
    (0x1D534, 'M', 'w'),
    (0x1D535, 'M', 'x'),
    (0x1D536, 'M', 'y'),
    (0x1D537, 'M', 'z'),
    (0x1D538, 'M', 'a'),
    (0x1D539, 'M', 'b'),
    (0x1D53A, 'X'),
    (0x1D53B, 'M', 'd'),
    (0x1D53C, 'M', 'e'),
    (0x1D53D, 'M', 'f'),
    (0x1D53E, 'M', 'g'),
    (0x1D53F, 'X'),
    (0x1D540, 'M', 'i'),
    (0x1D541, 'M', 'j'),
    (0x1D542, 'M', 'k'),
    (0x1D543, 'M', 'l'),
    (0x1D544, 'M', 'm'),
    (0x1D545, 'X'),
    (0x1D546, 'M', 'o'),
    (0x1D547, 'X'),
    (0x1D54A, 'M', 's'),
    (0x1D54B, 'M', 't'),
    (0x1D54C, 'M', 'u'),
    (0x1D54D, 'M', 'v'),
    (0x1D54E, 'M', 'w'),
    (0x1D54F, 'M', 'x'),
    (0x1D550, 'M', 'y'),
    (0x1D551, 'X'),
    (0x1D552, 'M', 'a'),
    (0x1D553, 'M', 'b'),
    (0x1D554, 'M', 'c'),
    (0x1D555, 'M', 'd'),
    (0x1D556, 'M', 'e'),
    ]

def _seg_64() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1D557, 'M', 'f'),
    (0x1D558, 'M', 'g'),
    (0x1D559, 'M', 'h'),
    (0x1D55A, 'M', 'i'),
    (0x1D55B, 'M', 'j'),
    (0x1D55C, 'M', 'k'),
    (0x1D55D, 'M', 'l'),
    (0x1D55E, 'M', 'm'),
    (0x1D55F, 'M', 'n'),
    (0x1D560, 'M', 'o'),
    (0x1D561, 'M', 'p'),
    (0x1D562, 'M', 'q'),
    (0x1D563, 'M', 'r'),
    (0x1D564, 'M', 's'),
    (0x1D565, 'M', 't'),
    (0x1D566, 'M', 'u'),
    (0x1D567, 'M', 'v'),
    (0x1D568, 'M', 'w'),
    (0x1D569, 'M', 'x'),
    (0x1D56A, 'M', 'y'),
    (0x1D56B, 'M', 'z'),
    (0x1D56C, 'M', 'a'),
    (0x1D56D, 'M', 'b'),
    (0x1D56E, 'M', 'c'),
    (0x1D56F, 'M', 'd'),
    (0x1D570, 'M', 'e'),
    (0x1D571, 'M', 'f'),
    (0x1D572, 'M', 'g'),
    (0x1D573, 'M', 'h'),
    (0x1D574, 'M', 'i'),
    (0x1D575, 'M', 'j'),
    (0x1D576, 'M', 'k'),
    (0x1D577, 'M', 'l'),
    (0x1D578, 'M', 'm'),
    (0x1D579, 'M', 'n'),
    (0x1D57A, 'M', 'o'),
    (0x1D57B, 'M', 'p'),
    (0x1D57C, 'M', 'q'),
    (0x1D57D, 'M', 'r'),
    (0x1D57E, 'M', 's'),
    (0x1D57F, 'M', 't'),
    (0x1D580, 'M', 'u'),
    (0x1D581, 'M', 'v'),
    (0x1D582, 'M', 'w'),
    (0x1D583, 'M', 'x'),
    (0x1D584, 'M', 'y'),
    (0x1D585, 'M', 'z'),
    (0x1D586, 'M', 'a'),
    (0x1D587, 'M', 'b'),
    (0x1D588, 'M', 'c'),
    (0x1D589, 'M', 'd'),
    (0x1D58A, 'M', 'e'),
    (0x1D58B, 'M', 'f'),
    (0x1D58C, 'M', 'g'),
    (0x1D58D, 'M', 'h'),
    (0x1D58E, 'M', 'i'),
    (0x1D58F, 'M', 'j'),
    (0x1D590, 'M', 'k'),
    (0x1D591, 'M', 'l'),
    (0x1D592, 'M', 'm'),
    (0x1D593, 'M', 'n'),
    (0x1D594, 'M', 'o'),
    (0x1D595, 'M', 'p'),
    (0x1D596, 'M', 'q'),
    (0x1D597, 'M', 'r'),
    (0x1D598, 'M', 's'),
    (0x1D599, 'M', 't'),
    (0x1D59A, 'M', 'u'),
    (0x1D59B, 'M', 'v'),
    (0x1D59C, 'M', 'w'),
    (0x1D59D, 'M', 'x'),
    (0x1D59E, 'M', 'y'),
    (0x1D59F, 'M', 'z'),
    (0x1D5A0, 'M', 'a'),
    (0x1D5A1, 'M', 'b'),
    (0x1D5A2, 'M', 'c'),
    (0x1D5A3, 'M', 'd'),
    (0x1D5A4, 'M', 'e'),
    (0x1D5A5, 'M', 'f'),
    (0x1D5A6, 'M', 'g'),
    (0x1D5A7, 'M', 'h'),
    (0x1D5A8, 'M', 'i'),
    (0x1D5A9, 'M', 'j'),
    (0x1D5AA, 'M', 'k'),
    (0x1D5AB, 'M', 'l'),
    (0x1D5AC, 'M', 'm'),
    (0x1D5AD, 'M', 'n'),
    (0x1D5AE, 'M', 'o'),
    (0x1D5AF, 'M', 'p'),
    (0x1D5B0, 'M', 'q'),
    (0x1D5B1, 'M', 'r'),
    (0x1D5B2, 'M', 's'),
    (0x1D5B3, 'M', 't'),
    (0x1D5B4, 'M', 'u'),
    (0x1D5B5, 'M', 'v'),
    (0x1D5B6, 'M', 'w'),
    (0x1D5B7, 'M', 'x'),
    (0x1D5B8, 'M', 'y'),
    (0x1D5B9, 'M', 'z'),
    (0x1D5BA, 'M', 'a'),
    ]

def _seg_65() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1D5BB, 'M', 'b'),
    (0x1D5BC, 'M', 'c'),
    (0x1D5BD, 'M', 'd'),
    (0x1D5BE, 'M', 'e'),
    (0x1D5BF, 'M', 'f'),
    (0x1D5C0, 'M', 'g'),
    (0x1D5C1, 'M', 'h'),
    (0x1D5C2, 'M', 'i'),
    (0x1D5C3, 'M', 'j'),
    (0x1D5C4, 'M', 'k'),
    (0x1D5C5, 'M', 'l'),
    (0x1D5C6, 'M', 'm'),
    (0x1D5C7, 'M', 'n'),
    (0x1D5C8, 'M', 'o'),
    (0x1D5C9, 'M', 'p'),
    (0x1D5CA, 'M', 'q'),
    (0x1D5CB, 'M', 'r'),
    (0x1D5CC, 'M', 's'),
    (0x1D5CD, 'M', 't'),
    (0x1D5CE, 'M', 'u'),
    (0x1D5CF, 'M', 'v'),
    (0x1D5D0, 'M', 'w'),
    (0x1D5D1, 'M', 'x'),
    (0x1D5D2, 'M', 'y'),
    (0x1D5D3, 'M', 'z'),
    (0x1D5D4, 'M', 'a'),
    (0x1D5D5, 'M', 'b'),
    (0x1D5D6, 'M', 'c'),
    (0x1D5D7, 'M', 'd'),
    (0x1D5D8, 'M', 'e'),
    (0x1D5D9, 'M', 'f'),
    (0x1D5DA, 'M', 'g'),
    (0x1D5DB, 'M', 'h'),
    (0x1D5DC, 'M', 'i'),
    (0x1D5DD, 'M', 'j'),
    (0x1D5DE, 'M', 'k'),
    (0x1D5DF, 'M', 'l'),
    (0x1D5E0, 'M', 'm'),
    (0x1D5E1, 'M', 'n'),
    (0x1D5E2, 'M', 'o'),
    (0x1D5E3, 'M', 'p'),
    (0x1D5E4, 'M', 'q'),
    (0x1D5E5, 'M', 'r'),
    (0x1D5E6, 'M', 's'),
    (0x1D5E7, 'M', 't'),
    (0x1D5E8, 'M', 'u'),
    (0x1D5E9, 'M', 'v'),
    (0x1D5EA, 'M', 'w'),
    (0x1D5EB, 'M', 'x'),
    (0x1D5EC, 'M', 'y'),
    (0x1D5ED, 'M', 'z'),
    (0x1D5EE, 'M', 'a'),
    (0x1D5EF, 'M', 'b'),
    (0x1D5F0, 'M', 'c'),
    (0x1D5F1, 'M', 'd'),
    (0x1D5F2, 'M', 'e'),
    (0x1D5F3, 'M', 'f'),
    (0x1D5F4, 'M', 'g'),
    (0x1D5F5, 'M', 'h'),
    (0x1D5F6, 'M', 'i'),
    (0x1D5F7, 'M', 'j'),
    (0x1D5F8, 'M', 'k'),
    (0x1D5F9, 'M', 'l'),
    (0x1D5FA, 'M', 'm'),
    (0x1D5FB, 'M', 'n'),
    (0x1D5FC, 'M', 'o'),
    (0x1D5FD, 'M', 'p'),
    (0x1D5FE, 'M', 'q'),
    (0x1D5FF, 'M', 'r'),
    (0x1D600, 'M', 's'),
    (0x1D601, 'M', 't'),
    (0x1D602, 'M', 'u'),
    (0x1D603, 'M', 'v'),
    (0x1D604, 'M', 'w'),
    (0x1D605, 'M', 'x'),
    (0x1D606, 'M', 'y'),
    (0x1D607, 'M', 'z'),
    (0x1D608, 'M', 'a'),
    (0x1D609, 'M', 'b'),
    (0x1D60A, 'M', 'c'),
    (0x1D60B, 'M', 'd'),
    (0x1D60C, 'M', 'e'),
    (0x1D60D, 'M', 'f'),
    (0x1D60E, 'M', 'g'),
    (0x1D60F, 'M', 'h'),
    (0x1D610, 'M', 'i'),
    (0x1D611, 'M', 'j'),
    (0x1D612, 'M', 'k'),
    (0x1D613, 'M', 'l'),
    (0x1D614, 'M', 'm'),
    (0x1D615, 'M', 'n'),
    (0x1D616, 'M', 'o'),
    (0x1D617, 'M', 'p'),
    (0x1D618, 'M', 'q'),
    (0x1D619, 'M', 'r'),
    (0x1D61A, 'M', 's'),
    (0x1D61B, 'M', 't'),
    (0x1D61C, 'M', 'u'),
    (0x1D61D, 'M', 'v'),
    (0x1D61E, 'M', 'w'),
    ]

def _seg_66() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1D61F, 'M', 'x'),
    (0x1D620, 'M', 'y'),
    (0x1D621, 'M', 'z'),
    (0x1D622, 'M', 'a'),
    (0x1D623, 'M', 'b'),
    (0x1D624, 'M', 'c'),
    (0x1D625, 'M', 'd'),
    (0x1D626, 'M', 'e'),
    (0x1D627, 'M', 'f'),
    (0x1D628, 'M', 'g'),
    (0x1D629, 'M', 'h'),
    (0x1D62A, 'M', 'i'),
    (0x1D62B, 'M', 'j'),
    (0x1D62C, 'M', 'k'),
    (0x1D62D, 'M', 'l'),
    (0x1D62E, 'M', 'm'),
    (0x1D62F, 'M', 'n'),
    (0x1D630, 'M', 'o'),
    (0x1D631, 'M', 'p'),
    (0x1D632, 'M', 'q'),
    (0x1D633, 'M', 'r'),
    (0x1D634, 'M', 's'),
    (0x1D635, 'M', 't'),
    (0x1D636, 'M', 'u'),
    (0x1D637, 'M', 'v'),
    (0x1D638, 'M', 'w'),
    (0x1D639, 'M', 'x'),
    (0x1D63A, 'M', 'y'),
    (0x1D63B, 'M', 'z'),
    (0x1D63C, 'M', 'a'),
    (0x1D63D, 'M', 'b'),
    (0x1D63E, 'M', 'c'),
    (0x1D63F, 'M', 'd'),
    (0x1D640, 'M', 'e'),
    (0x1D641, 'M', 'f'),
    (0x1D642, 'M', 'g'),
    (0x1D643, 'M', 'h'),
    (0x1D644, 'M', 'i'),
    (0x1D645, 'M', 'j'),
    (0x1D646, 'M', 'k'),
    (0x1D647, 'M', 'l'),
    (0x1D648, 'M', 'm'),
    (0x1D649, 'M', 'n'),
    (0x1D64A, 'M', 'o'),
    (0x1D64B, 'M', 'p'),
    (0x1D64C, 'M', 'q'),
    (0x1D64D, 'M', 'r'),
    (0x1D64E, 'M', 's'),
    (0x1D64F, 'M', 't'),
    (0x1D650, 'M', 'u'),
    (0x1D651, 'M', 'v'),
    (0x1D652, 'M', 'w'),
    (0x1D653, 'M', 'x'),
    (0x1D654, 'M', 'y'),
    (0x1D655, 'M', 'z'),
    (0x1D656, 'M', 'a'),
    (0x1D657, 'M', 'b'),
    (0x1D658, 'M', 'c'),
    (0x1D659, 'M', 'd'),
    (0x1D65A, 'M', 'e'),
    (0x1D65B, 'M', 'f'),
    (0x1D65C, 'M', 'g'),
    (0x1D65D, 'M', 'h'),
    (0x1D65E, 'M', 'i'),
    (0x1D65F, 'M', 'j'),
    (0x1D660, 'M', 'k'),
    (0x1D661, 'M', 'l'),
    (0x1D662, 'M', 'm'),
    (0x1D663, 'M', 'n'),
    (0x1D664, 'M', 'o'),
    (0x1D665, 'M', 'p'),
    (0x1D666, 'M', 'q'),
    (0x1D667, 'M', 'r'),
    (0x1D668, 'M', 's'),
    (0x1D669, 'M', 't'),
    (0x1D66A, 'M', 'u'),
    (0x1D66B, 'M', 'v'),
    (0x1D66C, 'M', 'w'),
    (0x1D66D, 'M', 'x'),
    (0x1D66E, 'M', 'y'),
    (0x1D66F, 'M', 'z'),
    (0x1D670, 'M', 'a'),
    (0x1D671, 'M', 'b'),
    (0x1D672, 'M', 'c'),
    (0x1D673, 'M', 'd'),
    (0x1D674, 'M', 'e'),
    (0x1D675, 'M', 'f'),
    (0x1D676, 'M', 'g'),
    (0x1D677, 'M', 'h'),
    (0x1D678, 'M', 'i'),
    (0x1D679, 'M', 'j'),
    (0x1D67A, 'M', 'k'),
    (0x1D67B, 'M', 'l'),
    (0x1D67C, 'M', 'm'),
    (0x1D67D, 'M', 'n'),
    (0x1D67E, 'M', 'o'),
    (0x1D67F, 'M', 'p'),
    (0x1D680, 'M', 'q'),
    (0x1D681, 'M', 'r'),
    (0x1D682, 'M', 's'),
    ]

def _seg_67() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1D683, 'M', 't'),
    (0x1D684, 'M', 'u'),
    (0x1D685, 'M', 'v'),
    (0x1D686, 'M', 'w'),
    (0x1D687, 'M', 'x'),
    (0x1D688, 'M', 'y'),
    (0x1D689, 'M', 'z'),
    (0x1D68A, 'M', 'a'),
    (0x1D68B, 'M', 'b'),
    (0x1D68C, 'M', 'c'),
    (0x1D68D, 'M', 'd'),
    (0x1D68E, 'M', 'e'),
    (0x1D68F, 'M', 'f'),
    (0x1D690, 'M', 'g'),
    (0x1D691, 'M', 'h'),
    (0x1D692, 'M', 'i'),
    (0x1D693, 'M', 'j'),
    (0x1D694, 'M', 'k'),
    (0x1D695, 'M', 'l'),
    (0x1D696, 'M', 'm'),
    (0x1D697, 'M', 'n'),
    (0x1D698, 'M', 'o'),
    (0x1D699, 'M', 'p'),
    (0x1D69A, 'M', 'q'),
    (0x1D69B, 'M', 'r'),
    (0x1D69C, 'M', 's'),
    (0x1D69D, 'M', 't'),
    (0x1D69E, 'M', 'u'),
    (0x1D69F, 'M', 'v'),
    (0x1D6A0, 'M', 'w'),
    (0x1D6A1, 'M', 'x'),
    (0x1D6A2, 'M', 'y'),
    (0x1D6A3, 'M', 'z'),
    (0x1D6A4, 'M', 'ı'),
    (0x1D6A5, 'M', 'ȷ'),
    (0x1D6A6, 'X'),
    (0x1D6A8, 'M', 'α'),
    (0x1D6A9, 'M', 'β'),
    (0x1D6AA, 'M', 'γ'),
    (0x1D6AB, 'M', 'δ'),
    (0x1D6AC, 'M', 'ε'),
    (0x1D6AD, 'M', 'ζ'),
    (0x1D6AE, 'M', 'η'),
    (0x1D6AF, 'M', 'θ'),
    (0x1D6B0, 'M', 'ι'),
    (0x1D6B1, 'M', 'κ'),
    (0x1D6B2, 'M', 'λ'),
    (0x1D6B3, 'M', 'μ'),
    (0x1D6B4, 'M', 'ν'),
    (0x1D6B5, 'M', 'ξ'),
    (0x1D6B6, 'M', 'ο'),
    (0x1D6B7, 'M', 'π'),
    (0x1D6B8, 'M', 'ρ'),
    (0x1D6B9, 'M', 'θ'),
    (0x1D6BA, 'M', 'σ'),
    (0x1D6BB, 'M', 'τ'),
    (0x1D6BC, 'M', 'υ'),
    (0x1D6BD, 'M', 'φ'),
    (0x1D6BE, 'M', 'χ'),
    (0x1D6BF, 'M', 'ψ'),
    (0x1D6C0, 'M', 'ω'),
    (0x1D6C1, 'M', '∇'),
    (0x1D6C2, 'M', 'α'),
    (0x1D6C3, 'M', 'β'),
    (0x1D6C4, 'M', 'γ'),
    (0x1D6C5, 'M', 'δ'),
    (0x1D6C6, 'M', 'ε'),
    (0x1D6C7, 'M', 'ζ'),
    (0x1D6C8, 'M', 'η'),
    (0x1D6C9, 'M', 'θ'),
    (0x1D6CA, 'M', 'ι'),
    (0x1D6CB, 'M', 'κ'),
    (0x1D6CC, 'M', 'λ'),
    (0x1D6CD, 'M', 'μ'),
    (0x1D6CE, 'M', 'ν'),
    (0x1D6CF, 'M', 'ξ'),
    (0x1D6D0, 'M', 'ο'),
    (0x1D6D1, 'M', 'π'),
    (0x1D6D2, 'M', 'ρ'),
    (0x1D6D3, 'M', 'σ'),
    (0x1D6D5, 'M', 'τ'),
    (0x1D6D6, 'M', 'υ'),
    (0x1D6D7, 'M', 'φ'),
    (0x1D6D8, 'M', 'χ'),
    (0x1D6D9, 'M', 'ψ'),
    (0x1D6DA, 'M', 'ω'),
    (0x1D6DB, 'M', '∂'),
    (0x1D6DC, 'M', 'ε'),
    (0x1D6DD, 'M', 'θ'),
    (0x1D6DE, 'M', 'κ'),
    (0x1D6DF, 'M', 'φ'),
    (0x1D6E0, 'M', 'ρ'),
    (0x1D6E1, 'M', 'π'),
    (0x1D6E2, 'M', 'α'),
    (0x1D6E3, 'M', 'β'),
    (0x1D6E4, 'M', 'γ'),
    (0x1D6E5, 'M', 'δ'),
    (0x1D6E6, 'M', 'ε'),
    (0x1D6E7, 'M', 'ζ'),
    (0x1D6E8, 'M', 'η'),
    ]

def _seg_68() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1D6E9, 'M', 'θ'),
    (0x1D6EA, 'M', 'ι'),
    (0x1D6EB, 'M', 'κ'),
    (0x1D6EC, 'M', 'λ'),
    (0x1D6ED, 'M', 'μ'),
    (0x1D6EE, 'M', 'ν'),
    (0x1D6EF, 'M', 'ξ'),
    (0x1D6F0, 'M', 'ο'),
    (0x1D6F1, 'M', 'π'),
    (0x1D6F2, 'M', 'ρ'),
    (0x1D6F3, 'M', 'θ'),
    (0x1D6F4, 'M', 'σ'),
    (0x1D6F5, 'M', 'τ'),
    (0x1D6F6, 'M', 'υ'),
    (0x1D6F7, 'M', 'φ'),
    (0x1D6F8, 'M', 'χ'),
    (0x1D6F9, 'M', 'ψ'),
    (0x1D6FA, 'M', 'ω'),
    (0x1D6FB, 'M', '∇'),
    (0x1D6FC, 'M', 'α'),
    (0x1D6FD, 'M', 'β'),
    (0x1D6FE, 'M', 'γ'),
    (0x1D6FF, 'M', 'δ'),
    (0x1D700, 'M', 'ε'),
    (0x1D701, 'M', 'ζ'),
    (0x1D702, 'M', 'η'),
    (0x1D703, 'M', 'θ'),
    (0x1D704, 'M', 'ι'),
    (0x1D705, 'M', 'κ'),
    (0x1D706, 'M', 'λ'),
    (0x1D707, 'M', 'μ'),
    (0x1D708, 'M', 'ν'),
    (0x1D709, 'M', 'ξ'),
    (0x1D70A, 'M', 'ο'),
    (0x1D70B, 'M', 'π'),
    (0x1D70C, 'M', 'ρ'),
    (0x1D70D, 'M', 'σ'),
    (0x1D70F, 'M', 'τ'),
    (0x1D710, 'M', 'υ'),
    (0x1D711, 'M', 'φ'),
    (0x1D712, 'M', 'χ'),
    (0x1D713, 'M', 'ψ'),
    (0x1D714, 'M', 'ω'),
    (0x1D715, 'M', '∂'),
    (0x1D716, 'M', 'ε'),
    (0x1D717, 'M', 'θ'),
    (0x1D718, 'M', 'κ'),
    (0x1D719, 'M', 'φ'),
    (0x1D71A, 'M', 'ρ'),
    (0x1D71B, 'M', 'π'),
    (0x1D71C, 'M', 'α'),
    (0x1D71D, 'M', 'β'),
    (0x1D71E, 'M', 'γ'),
    (0x1D71F, 'M', 'δ'),
    (0x1D720, 'M', 'ε'),
    (0x1D721, 'M', 'ζ'),
    (0x1D722, 'M', 'η'),
    (0x1D723, 'M', 'θ'),
    (0x1D724, 'M', 'ι'),
    (0x1D725, 'M', 'κ'),
    (0x1D726, 'M', 'λ'),
    (0x1D727, 'M', 'μ'),
    (0x1D728, 'M', 'ν'),
    (0x1D729, 'M', 'ξ'),
    (0x1D72A, 'M', 'ο'),
    (0x1D72B, 'M', 'π'),
    (0x1D72C, 'M', 'ρ'),
    (0x1D72D, 'M', 'θ'),
    (0x1D72E, 'M', 'σ'),
    (0x1D72F, 'M', 'τ'),
    (0x1D730, 'M', 'υ'),
    (0x1D731, 'M', 'φ'),
    (0x1D732, 'M', 'χ'),
    (0x1D733, 'M', 'ψ'),
    (0x1D734, 'M', 'ω'),
    (0x1D735, 'M', '∇'),
    (0x1D736, 'M', 'α'),
    (0x1D737, 'M', 'β'),
    (0x1D738, 'M', 'γ'),
    (0x1D739, 'M', 'δ'),
    (0x1D73A, 'M', 'ε'),
    (0x1D73B, 'M', 'ζ'),
    (0x1D73C, 'M', 'η'),
    (0x1D73D, 'M', 'θ'),
    (0x1D73E, 'M', 'ι'),
    (0x1D73F, 'M', 'κ'),
    (0x1D740, 'M', 'λ'),
    (0x1D741, 'M', 'μ'),
    (0x1D742, 'M', 'ν'),
    (0x1D743, 'M', 'ξ'),
    (0x1D744, 'M', 'ο'),
    (0x1D745, 'M', 'π'),
    (0x1D746, 'M', 'ρ'),
    (0x1D747, 'M', 'σ'),
    (0x1D749, 'M', 'τ'),
    (0x1D74A, 'M', 'υ'),
    (0x1D74B, 'M', 'φ'),
    (0x1D74C, 'M', 'χ'),
    (0x1D74D, 'M', 'ψ'),
    (0x1D74E, 'M', 'ω'),
    ]

def _seg_69() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1D74F, 'M', '∂'),
    (0x1D750, 'M', 'ε'),
    (0x1D751, 'M', 'θ'),
    (0x1D752, 'M', 'κ'),
    (0x1D753, 'M', 'φ'),
    (0x1D754, 'M', 'ρ'),
    (0x1D755, 'M', 'π'),
    (0x1D756, 'M', 'α'),
    (0x1D757, 'M', 'β'),
    (0x1D758, 'M', 'γ'),
    (0x1D759, 'M', 'δ'),
    (0x1D75A, 'M', 'ε'),
    (0x1D75B, 'M', 'ζ'),
    (0x1D75C, 'M', 'η'),
    (0x1D75D, 'M', 'θ'),
    (0x1D75E, 'M', 'ι'),
    (0x1D75F, 'M', 'κ'),
    (0x1D760, 'M', 'λ'),
    (0x1D761, 'M', 'μ'),
    (0x1D762, 'M', 'ν'),
    (0x1D763, 'M', 'ξ'),
    (0x1D764, 'M', 'ο'),
    (0x1D765, 'M', 'π'),
    (0x1D766, 'M', 'ρ'),
    (0x1D767, 'M', 'θ'),
    (0x1D768, 'M', 'σ'),
    (0x1D769, 'M', 'τ'),
    (0x1D76A, 'M', 'υ'),
    (0x1D76B, 'M', 'φ'),
    (0x1D76C, 'M', 'χ'),
    (0x1D76D, 'M', 'ψ'),
    (0x1D76E, 'M', 'ω'),
    (0x1D76F, 'M', '∇'),
    (0x1D770, 'M', 'α'),
    (0x1D771, 'M', 'β'),
    (0x1D772, 'M', 'γ'),
    (0x1D773, 'M', 'δ'),
    (0x1D774, 'M', 'ε'),
    (0x1D775, 'M', 'ζ'),
    (0x1D776, 'M', 'η'),
    (0x1D777, 'M', 'θ'),
    (0x1D778, 'M', 'ι'),
    (0x1D779, 'M', 'κ'),
    (0x1D77A, 'M', 'λ'),
    (0x1D77B, 'M', 'μ'),
    (0x1D77C, 'M', 'ν'),
    (0x1D77D, 'M', 'ξ'),
    (0x1D77E, 'M', 'ο'),
    (0x1D77F, 'M', 'π'),
    (0x1D780, 'M', 'ρ'),
    (0x1D781, 'M', 'σ'),
    (0x1D783, 'M', 'τ'),
    (0x1D784, 'M', 'υ'),
    (0x1D785, 'M', 'φ'),
    (0x1D786, 'M', 'χ'),
    (0x1D787, 'M', 'ψ'),
    (0x1D788, 'M', 'ω'),
    (0x1D789, 'M', '∂'),
    (0x1D78A, 'M', 'ε'),
    (0x1D78B, 'M', 'θ'),
    (0x1D78C, 'M', 'κ'),
    (0x1D78D, 'M', 'φ'),
    (0x1D78E, 'M', 'ρ'),
    (0x1D78F, 'M', 'π'),
    (0x1D790, 'M', 'α'),
    (0x1D791, 'M', 'β'),
    (0x1D792, 'M', 'γ'),
    (0x1D793, 'M', 'δ'),
    (0x1D794, 'M', 'ε'),
    (0x1D795, 'M', 'ζ'),
    (0x1D796, 'M', 'η'),
    (0x1D797, 'M', 'θ'),
    (0x1D798, 'M', 'ι'),
    (0x1D799, 'M', 'κ'),
    (0x1D79A, 'M', 'λ'),
    (0x1D79B, 'M', 'μ'),
    (0x1D79C, 'M', 'ν'),
    (0x1D79D, 'M', 'ξ'),
    (0x1D79E, 'M', 'ο'),
    (0x1D79F, 'M', 'π'),
    (0x1D7A0, 'M', 'ρ'),
    (0x1D7A1, 'M', 'θ'),
    (0x1D7A2, 'M', 'σ'),
    (0x1D7A3, 'M', 'τ'),
    (0x1D7A4, 'M', 'υ'),
    (0x1D7A5, 'M', 'φ'),
    (0x1D7A6, 'M', 'χ'),
    (0x1D7A7, 'M', 'ψ'),
    (0x1D7A8, 'M', 'ω'),
    (0x1D7A9, 'M', '∇'),
    (0x1D7AA, 'M', 'α'),
    (0x1D7AB, 'M', 'β'),
    (0x1D7AC, 'M', 'γ'),
    (0x1D7AD, 'M', 'δ'),
    (0x1D7AE, 'M', 'ε'),
    (0x1D7AF, 'M', 'ζ'),
    (0x1D7B0, 'M', 'η'),
    (0x1D7B1, 'M', 'θ'),
    (0x1D7B2, 'M', 'ι'),
    (0x1D7B3, 'M', 'κ'),
    ]

def _seg_70() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1D7B4, 'M', 'λ'),
    (0x1D7B5, 'M', 'μ'),
    (0x1D7B6, 'M', 'ν'),
    (0x1D7B7, 'M', 'ξ'),
    (0x1D7B8, 'M', 'ο'),
    (0x1D7B9, 'M', 'π'),
    (0x1D7BA, 'M', 'ρ'),
    (0x1D7BB, 'M', 'σ'),
    (0x1D7BD, 'M', 'τ'),
    (0x1D7BE, 'M', 'υ'),
    (0x1D7BF, 'M', 'φ'),
    (0x1D7C0, 'M', 'χ'),
    (0x1D7C1, 'M', 'ψ'),
    (0x1D7C2, 'M', 'ω'),
    (0x1D7C3, 'M', '∂'),
    (0x1D7C4, 'M', 'ε'),
    (0x1D7C5, 'M', 'θ'),
    (0x1D7C6, 'M', 'κ'),
    (0x1D7C7, 'M', 'φ'),
    (0x1D7C8, 'M', 'ρ'),
    (0x1D7C9, 'M', 'π'),
    (0x1D7CA, 'M', 'ϝ'),
    (0x1D7CC, 'X'),
    (0x1D7CE, 'M', '0'),
    (0x1D7CF, 'M', '1'),
    (0x1D7D0, 'M', '2'),
    (0x1D7D1, 'M', '3'),
    (0x1D7D2, 'M', '4'),
    (0x1D7D3, 'M', '5'),
    (0x1D7D4, 'M', '6'),
    (0x1D7D5, 'M', '7'),
    (0x1D7D6, 'M', '8'),
    (0x1D7D7, 'M', '9'),
    (0x1D7D8, 'M', '0'),
    (0x1D7D9, 'M', '1'),
    (0x1D7DA, 'M', '2'),
    (0x1D7DB, 'M', '3'),
    (0x1D7DC, 'M', '4'),
    (0x1D7DD, 'M', '5'),
    (0x1D7DE, 'M', '6'),
    (0x1D7DF, 'M', '7'),
    (0x1D7E0, 'M', '8'),
    (0x1D7E1, 'M', '9'),
    (0x1D7E2, 'M', '0'),
    (0x1D7E3, 'M', '1'),
    (0x1D7E4, 'M', '2'),
    (0x1D7E5, 'M', '3'),
    (0x1D7E6, 'M', '4'),
    (0x1D7E7, 'M', '5'),
    (0x1D7E8, 'M', '6'),
    (0x1D7E9, 'M', '7'),
    (0x1D7EA, 'M', '8'),
    (0x1D7EB, 'M', '9'),
    (0x1D7EC, 'M', '0'),
    (0x1D7ED, 'M', '1'),
    (0x1D7EE, 'M', '2'),
    (0x1D7EF, 'M', '3'),
    (0x1D7F0, 'M', '4'),
    (0x1D7F1, 'M', '5'),
    (0x1D7F2, 'M', '6'),
    (0x1D7F3, 'M', '7'),
    (0x1D7F4, 'M', '8'),
    (0x1D7F5, 'M', '9'),
    (0x1D7F6, 'M', '0'),
    (0x1D7F7, 'M', '1'),
    (0x1D7F8, 'M', '2'),
    (0x1D7F9, 'M', '3'),
    (0x1D7FA, 'M', '4'),
    (0x1D7FB, 'M', '5'),
    (0x1D7FC, 'M', '6'),
    (0x1D7FD, 'M', '7'),
    (0x1D7FE, 'M', '8'),
    (0x1D7FF, 'M', '9'),
    (0x1D800, 'V'),
    (0x1DA8C, 'X'),
    (0x1DA9B, 'V'),
    (0x1DAA0, 'X'),
    (0x1DAA1, 'V'),
    (0x1DAB0, 'X'),
    (0x1DF00, 'V'),
    (0x1DF1F, 'X'),
    (0x1DF25, 'V'),
    (0x1DF2B, 'X'),
    (0x1E000, 'V'),
    (0x1E007, 'X'),
    (0x1E008, 'V'),
    (0x1E019, 'X'),
    (0x1E01B, 'V'),
    (0x1E022, 'X'),
    (0x1E023, 'V'),
    (0x1E025, 'X'),
    (0x1E026, 'V'),
    (0x1E02B, 'X'),
    (0x1E030, 'M', 'а'),
    (0x1E031, 'M', 'б'),
    (0x1E032, 'M', 'в'),
    (0x1E033, 'M', 'г'),
    (0x1E034, 'M', 'д'),
    (0x1E035, 'M', 'е'),
    (0x1E036, 'M', 'ж'),
    ]

def _seg_71() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1E037, 'M', 'з'),
    (0x1E038, 'M', 'и'),
    (0x1E039, 'M', 'к'),
    (0x1E03A, 'M', 'л'),
    (0x1E03B, 'M', 'м'),
    (0x1E03C, 'M', 'о'),
    (0x1E03D, 'M', 'п'),
    (0x1E03E, 'M', 'р'),
    (0x1E03F, 'M', 'с'),
    (0x1E040, 'M', 'т'),
    (0x1E041, 'M', 'у'),
    (0x1E042, 'M', 'ф'),
    (0x1E043, 'M', 'х'),
    (0x1E044, 'M', 'ц'),
    (0x1E045, 'M', 'ч'),
    (0x1E046, 'M', 'ш'),
    (0x1E047, 'M', 'ы'),
    (0x1E048, 'M', 'э'),
    (0x1E049, 'M', 'ю'),
    (0x1E04A, 'M', 'ꚉ'),
    (0x1E04B, 'M', 'ә'),
    (0x1E04C, 'M', 'і'),
    (0x1E04D, 'M', 'ј'),
    (0x1E04E, 'M', 'ө'),
    (0x1E04F, 'M', 'ү'),
    (0x1E050, 'M', 'ӏ'),
    (0x1E051, 'M', 'а'),
    (0x1E052, 'M', 'б'),
    (0x1E053, 'M', 'в'),
    (0x1E054, 'M', 'г'),
    (0x1E055, 'M', 'д'),
    (0x1E056, 'M', 'е'),
    (0x1E057, 'M', 'ж'),
    (0x1E058, 'M', 'з'),
    (0x1E059, 'M', 'и'),
    (0x1E05A, 'M', 'к'),
    (0x1E05B, 'M', 'л'),
    (0x1E05C, 'M', 'о'),
    (0x1E05D, 'M', 'п'),
    (0x1E05E, 'M', 'с'),
    (0x1E05F, 'M', 'у'),
    (0x1E060, 'M', 'ф'),
    (0x1E061, 'M', 'х'),
    (0x1E062, 'M', 'ц'),
    (0x1E063, 'M', 'ч'),
    (0x1E064, 'M', 'ш'),
    (0x1E065, 'M', 'ъ'),
    (0x1E066, 'M', 'ы'),
    (0x1E067, 'M', 'ґ'),
    (0x1E068, 'M', 'і'),
    (0x1E069, 'M', 'ѕ'),
    (0x1E06A, 'M', 'џ'),
    (0x1E06B, 'M', 'ҫ'),
    (0x1E06C, 'M', 'ꙑ'),
    (0x1E06D, 'M', 'ұ'),
    (0x1E06E, 'X'),
    (0x1E08F, 'V'),
    (0x1E090, 'X'),
    (0x1E100, 'V'),
    (0x1E12D, 'X'),
    (0x1E130, 'V'),
    (0x1E13E, 'X'),
    (0x1E140, 'V'),
    (0x1E14A, 'X'),
    (0x1E14E, 'V'),
    (0x1E150, 'X'),
    (0x1E290, 'V'),
    (0x1E2AF, 'X'),
    (0x1E2C0, 'V'),
    (0x1E2FA, 'X'),
    (0x1E2FF, 'V'),
    (0x1E300, 'X'),
    (0x1E4D0, 'V'),
    (0x1E4FA, 'X'),
    (0x1E7E0, 'V'),
    (0x1E7E7, 'X'),
    (0x1E7E8, 'V'),
    (0x1E7EC, 'X'),
    (0x1E7ED, 'V'),
    (0x1E7EF, 'X'),
    (0x1E7F0, 'V'),
    (0x1E7FF, 'X'),
    (0x1E800, 'V'),
    (0x1E8C5, 'X'),
    (0x1E8C7, 'V'),
    (0x1E8D7, 'X'),
    (0x1E900, 'M', '𞤢'),
    (0x1E901, 'M', '𞤣'),
    (0x1E902, 'M', '𞤤'),
    (0x1E903, 'M', '𞤥'),
    (0x1E904, 'M', '𞤦'),
    (0x1E905, 'M', '𞤧'),
    (0x1E906, 'M', '𞤨'),
    (0x1E907, 'M', '𞤩'),
    (0x1E908, 'M', '𞤪'),
    (0x1E909, 'M', '𞤫'),
    (0x1E90A, 'M', '𞤬'),
    (0x1E90B, 'M', '𞤭'),
    (0x1E90C, 'M', '𞤮'),
    (0x1E90D, 'M', '𞤯'),
    ]

def _seg_72() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1E90E, 'M', '𞤰'),
    (0x1E90F, 'M', '𞤱'),
    (0x1E910, 'M', '𞤲'),
    (0x1E911, 'M', '𞤳'),
    (0x1E912, 'M', '𞤴'),
    (0x1E913, 'M', '𞤵'),
    (0x1E914, 'M', '𞤶'),
    (0x1E915, 'M', '𞤷'),
    (0x1E916, 'M', '𞤸'),
    (0x1E917, 'M', '𞤹'),
    (0x1E918, 'M', '𞤺'),
    (0x1E919, 'M', '𞤻'),
    (0x1E91A, 'M', '𞤼'),
    (0x1E91B, 'M', '𞤽'),
    (0x1E91C, 'M', '𞤾'),
    (0x1E91D, 'M', '𞤿'),
    (0x1E91E, 'M', '𞥀'),
    (0x1E91F, 'M', '𞥁'),
    (0x1E920, 'M', '𞥂'),
    (0x1E921, 'M', '𞥃'),
    (0x1E922, 'V'),
    (0x1E94C, 'X'),
    (0x1E950, 'V'),
    (0x1E95A, 'X'),
    (0x1E95E, 'V'),
    (0x1E960, 'X'),
    (0x1EC71, 'V'),
    (0x1ECB5, 'X'),
    (0x1ED01, 'V'),
    (0x1ED3E, 'X'),
    (0x1EE00, 'M', 'ا'),
    (0x1EE01, 'M', 'ب'),
    (0x1EE02, 'M', 'ج'),
    (0x1EE03, 'M', 'د'),
    (0x1EE04, 'X'),
    (0x1EE05, 'M', 'و'),
    (0x1EE06, 'M', 'ز'),
    (0x1EE07, 'M', 'ح'),
    (0x1EE08, 'M', 'ط'),
    (0x1EE09, 'M', 'ي'),
    (0x1EE0A, 'M', 'ك'),
    (0x1EE0B, 'M', 'ل'),
    (0x1EE0C, 'M', 'م'),
    (0x1EE0D, 'M', 'ن'),
    (0x1EE0E, 'M', 'س'),
    (0x1EE0F, 'M', 'ع'),
    (0x1EE10, 'M', 'ف'),
    (0x1EE11, 'M', 'ص'),
    (0x1EE12, 'M', 'ق'),
    (0x1EE13, 'M', 'ر'),
    (0x1EE14, 'M', 'ش'),
    (0x1EE15, 'M', 'ت'),
    (0x1EE16, 'M', 'ث'),
    (0x1EE17, 'M', 'خ'),
    (0x1EE18, 'M', 'ذ'),
    (0x1EE19, 'M', 'ض'),
    (0x1EE1A, 'M', 'ظ'),
    (0x1EE1B, 'M', 'غ'),
    (0x1EE1C, 'M', 'ٮ'),
    (0x1EE1D, 'M', 'ں'),
    (0x1EE1E, 'M', 'ڡ'),
    (0x1EE1F, 'M', 'ٯ'),
    (0x1EE20, 'X'),
    (0x1EE21, 'M', 'ب'),
    (0x1EE22, 'M', 'ج'),
    (0x1EE23, 'X'),
    (0x1EE24, 'M', 'ه'),
    (0x1EE25, 'X'),
    (0x1EE27, 'M', 'ح'),
    (0x1EE28, 'X'),
    (0x1EE29, 'M', 'ي'),
    (0x1EE2A, 'M', 'ك'),
    (0x1EE2B, 'M', 'ل'),
    (0x1EE2C, 'M', 'م'),
    (0x1EE2D, 'M', 'ن'),
    (0x1EE2E, 'M', 'س'),
    (0x1EE2F, 'M', 'ع'),
    (0x1EE30, 'M', 'ف'),
    (0x1EE31, 'M', 'ص'),
    (0x1EE32, 'M', 'ق'),
    (0x1EE33, 'X'),
    (0x1EE34, 'M', 'ش'),
    (0x1EE35, 'M', 'ت'),
    (0x1EE36, 'M', 'ث'),
    (0x1EE37, 'M', 'خ'),
    (0x1EE38, 'X'),
    (0x1EE39, 'M', 'ض'),
    (0x1EE3A, 'X'),
    (0x1EE3B, 'M', 'غ'),
    (0x1EE3C, 'X'),
    (0x1EE42, 'M', 'ج'),
    (0x1EE43, 'X'),
    (0x1EE47, 'M', 'ح'),
    (0x1EE48, 'X'),
    (0x1EE49, 'M', 'ي'),
    (0x1EE4A, 'X'),
    (0x1EE4B, 'M', 'ل'),
    (0x1EE4C, 'X'),
    (0x1EE4D, 'M', 'ن'),
    (0x1EE4E, 'M', 'س'),
    ]

def _seg_73() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1EE4F, 'M', 'ع'),
    (0x1EE50, 'X'),
    (0x1EE51, 'M', 'ص'),
    (0x1EE52, 'M', 'ق'),
    (0x1EE53, 'X'),
    (0x1EE54, 'M', 'ش'),
    (0x1EE55, 'X'),
    (0x1EE57, 'M', 'خ'),
    (0x1EE58, 'X'),
    (0x1EE59, 'M', 'ض'),
    (0x1EE5A, 'X'),
    (0x1EE5B, 'M', 'غ'),
    (0x1EE5C, 'X'),
    (0x1EE5D, 'M', 'ں'),
    (0x1EE5E, 'X'),
    (0x1EE5F, 'M', 'ٯ'),
    (0x1EE60, 'X'),
    (0x1EE61, 'M', 'ب'),
    (0x1EE62, 'M', 'ج'),
    (0x1EE63, 'X'),
    (0x1EE64, 'M', 'ه'),
    (0x1EE65, 'X'),
    (0x1EE67, 'M', 'ح'),
    (0x1EE68, 'M', 'ط'),
    (0x1EE69, 'M', 'ي'),
    (0x1EE6A, 'M', 'ك'),
    (0x1EE6B, 'X'),
    (0x1EE6C, 'M', 'م'),
    (0x1EE6D, 'M', 'ن'),
    (0x1EE6E, 'M', 'س'),
    (0x1EE6F, 'M', 'ع'),
    (0x1EE70, 'M', 'ف'),
    (0x1EE71, 'M', 'ص'),
    (0x1EE72, 'M', 'ق'),
    (0x1EE73, 'X'),
    (0x1EE74, 'M', 'ش'),
    (0x1EE75, 'M', 'ت'),
    (0x1EE76, 'M', 'ث'),
    (0x1EE77, 'M', 'خ'),
    (0x1EE78, 'X'),
    (0x1EE79, 'M', 'ض'),
    (0x1EE7A, 'M', 'ظ'),
    (0x1EE7B, 'M', 'غ'),
    (0x1EE7C, 'M', 'ٮ'),
    (0x1EE7D, 'X'),
    (0x1EE7E, 'M', 'ڡ'),
    (0x1EE7F, 'X'),
    (0x1EE80, 'M', 'ا'),
    (0x1EE81, 'M', 'ب'),
    (0x1EE82, 'M', 'ج'),
    (0x1EE83, 'M', 'د'),
    (0x1EE84, 'M', 'ه'),
    (0x1EE85, 'M', 'و'),
    (0x1EE86, 'M', 'ز'),
    (0x1EE87, 'M', 'ح'),
    (0x1EE88, 'M', 'ط'),
    (0x1EE89, 'M', 'ي'),
    (0x1EE8A, 'X'),
    (0x1EE8B, 'M', 'ل'),
    (0x1EE8C, 'M', 'م'),
    (0x1EE8D, 'M', 'ن'),
    (0x1EE8E, 'M', 'س'),
    (0x1EE8F, 'M', 'ع'),
    (0x1EE90, 'M', 'ف'),
    (0x1EE91, 'M', 'ص'),
    (0x1EE92, 'M', 'ق'),
    (0x1EE93, 'M', 'ر'),
    (0x1EE94, 'M', 'ش'),
    (0x1EE95, 'M', 'ت'),
    (0x1EE96, 'M', 'ث'),
    (0x1EE97, 'M', 'خ'),
    (0x1EE98, 'M', 'ذ'),
    (0x1EE99, 'M', 'ض'),
    (0x1EE9A, 'M', 'ظ'),
    (0x1EE9B, 'M', 'غ'),
    (0x1EE9C, 'X'),
    (0x1EEA1, 'M', 'ب'),
    (0x1EEA2, 'M', 'ج'),
    (0x1EEA3, 'M', 'د'),
    (0x1EEA4, 'X'),
    (0x1EEA5, 'M', 'و'),
    (0x1EEA6, 'M', 'ز'),
    (0x1EEA7, 'M', 'ح'),
    (0x1EEA8, 'M', 'ط'),
    (0x1EEA9, 'M', 'ي'),
    (0x1EEAA, 'X'),
    (0x1EEAB, 'M', 'ل'),
    (0x1EEAC, 'M', 'م'),
    (0x1EEAD, 'M', 'ن'),
    (0x1EEAE, 'M', 'س'),
    (0x1EEAF, 'M', 'ع'),
    (0x1EEB0, 'M', 'ف'),
    (0x1EEB1, 'M', 'ص'),
    (0x1EEB2, 'M', 'ق'),
    (0x1EEB3, 'M', 'ر'),
    (0x1EEB4, 'M', 'ش'),
    (0x1EEB5, 'M', 'ت'),
    (0x1EEB6, 'M', 'ث'),
    (0x1EEB7, 'M', 'خ'),
    (0x1EEB8, 'M', 'ذ'),
    ]

def _seg_74() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1EEB9, 'M', 'ض'),
    (0x1EEBA, 'M', 'ظ'),
    (0x1EEBB, 'M', 'غ'),
    (0x1EEBC, 'X'),
    (0x1EEF0, 'V'),
    (0x1EEF2, 'X'),
    (0x1F000, 'V'),
    (0x1F02C, 'X'),
    (0x1F030, 'V'),
    (0x1F094, 'X'),
    (0x1F0A0, 'V'),
    (0x1F0AF, 'X'),
    (0x1F0B1, 'V'),
    (0x1F0C0, 'X'),
    (0x1F0C1, 'V'),
    (0x1F0D0, 'X'),
    (0x1F0D1, 'V'),
    (0x1F0F6, 'X'),
    (0x1F101, '3', '0,'),
    (0x1F102, '3', '1,'),
    (0x1F103, '3', '2,'),
    (0x1F104, '3', '3,'),
    (0x1F105, '3', '4,'),
    (0x1F106, '3', '5,'),
    (0x1F107, '3', '6,'),
    (0x1F108, '3', '7,'),
    (0x1F109, '3', '8,'),
    (0x1F10A, '3', '9,'),
    (0x1F10B, 'V'),
    (0x1F110, '3', '(a)'),
    (0x1F111, '3', '(b)'),
    (0x1F112, '3', '(c)'),
    (0x1F113, '3', '(d)'),
    (0x1F114, '3', '(e)'),
    (0x1F115, '3', '(f)'),
    (0x1F116, '3', '(g)'),
    (0x1F117, '3', '(h)'),
    (0x1F118, '3', '(i)'),
    (0x1F119, '3', '(j)'),
    (0x1F11A, '3', '(k)'),
    (0x1F11B, '3', '(l)'),
    (0x1F11C, '3', '(m)'),
    (0x1F11D, '3', '(n)'),
    (0x1F11E, '3', '(o)'),
    (0x1F11F, '3', '(p)'),
    (0x1F120, '3', '(q)'),
    (0x1F121, '3', '(r)'),
    (0x1F122, '3', '(s)'),
    (0x1F123, '3', '(t)'),
    (0x1F124, '3', '(u)'),
    (0x1F125, '3', '(v)'),
    (0x1F126, '3', '(w)'),
    (0x1F127, '3', '(x)'),
    (0x1F128, '3', '(y)'),
    (0x1F129, '3', '(z)'),
    (0x1F12A, 'M', '〔s〕'),
    (0x1F12B, 'M', 'c'),
    (0x1F12C, 'M', 'r'),
    (0x1F12D, 'M', 'cd'),
    (0x1F12E, 'M', 'wz'),
    (0x1F12F, 'V'),
    (0x1F130, 'M', 'a'),
    (0x1F131, 'M', 'b'),
    (0x1F132, 'M', 'c'),
    (0x1F133, 'M', 'd'),
    (0x1F134, 'M', 'e'),
    (0x1F135, 'M', 'f'),
    (0x1F136, 'M', 'g'),
    (0x1F137, 'M', 'h'),
    (0x1F138, 'M', 'i'),
    (0x1F139, 'M', 'j'),
    (0x1F13A, 'M', 'k'),
    (0x1F13B, 'M', 'l'),
    (0x1F13C, 'M', 'm'),
    (0x1F13D, 'M', 'n'),
    (0x1F13E, 'M', 'o'),
    (0x1F13F, 'M', 'p'),
    (0x1F140, 'M', 'q'),
    (0x1F141, 'M', 'r'),
    (0x1F142, 'M', 's'),
    (0x1F143, 'M', 't'),
    (0x1F144, 'M', 'u'),
    (0x1F145, 'M', 'v'),
    (0x1F146, 'M', 'w'),
    (0x1F147, 'M', 'x'),
    (0x1F148, 'M', 'y'),
    (0x1F149, 'M', 'z'),
    (0x1F14A, 'M', 'hv'),
    (0x1F14B, 'M', 'mv'),
    (0x1F14C, 'M', 'sd'),
    (0x1F14D, 'M', 'ss'),
    (0x1F14E, 'M', 'ppv'),
    (0x1F14F, 'M', 'wc'),
    (0x1F150, 'V'),
    (0x1F16A, 'M', 'mc'),
    (0x1F16B, 'M', 'md'),
    (0x1F16C, 'M', 'mr'),
    (0x1F16D, 'V'),
    (0x1F190, 'M', 'dj'),
    (0x1F191, 'V'),
    ]

def _seg_75() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1F1AE, 'X'),
    (0x1F1E6, 'V'),
    (0x1F200, 'M', 'ほか'),
    (0x1F201, 'M', 'ココ'),
    (0x1F202, 'M', 'サ'),
    (0x1F203, 'X'),
    (0x1F210, 'M', '手'),
    (0x1F211, 'M', '字'),
    (0x1F212, 'M', '双'),
    (0x1F213, 'M', 'デ'),
    (0x1F214, 'M', '二'),
    (0x1F215, 'M', '多'),
    (0x1F216, 'M', '解'),
    (0x1F217, 'M', '天'),
    (0x1F218, 'M', '交'),
    (0x1F219, 'M', '映'),
    (0x1F21A, 'M', '無'),
    (0x1F21B, 'M', '料'),
    (0x1F21C, 'M', '前'),
    (0x1F21D, 'M', '後'),
    (0x1F21E, 'M', '再'),
    (0x1F21F, 'M', '新'),
    (0x1F220, 'M', '初'),
    (0x1F221, 'M', '終'),
    (0x1F222, 'M', '生'),
    (0x1F223, 'M', '販'),
    (0x1F224, 'M', '声'),
    (0x1F225, 'M', '吹'),
    (0x1F226, 'M', '演'),
    (0x1F227, 'M', '投'),
    (0x1F228, 'M', '捕'),
    (0x1F229, 'M', '一'),
    (0x1F22A, 'M', '三'),
    (0x1F22B, 'M', '遊'),
    (0x1F22C, 'M', '左'),
    (0x1F22D, 'M', '中'),
    (0x1F22E, 'M', '右'),
    (0x1F22F, 'M', '指'),
    (0x1F230, 'M', '走'),
    (0x1F231, 'M', '打'),
    (0x1F232, 'M', '禁'),
    (0x1F233, 'M', '空'),
    (0x1F234, 'M', '合'),
    (0x1F235, 'M', '満'),
    (0x1F236, 'M', '有'),
    (0x1F237, 'M', '月'),
    (0x1F238, 'M', '申'),
    (0x1F239, 'M', '割'),
    (0x1F23A, 'M', '営'),
    (0x1F23B, 'M', '配'),
    (0x1F23C, 'X'),
    (0x1F240, 'M', '〔本〕'),
    (0x1F241, 'M', '〔三〕'),
    (0x1F242, 'M', '〔二〕'),
    (0x1F243, 'M', '〔安〕'),
    (0x1F244, 'M', '〔点〕'),
    (0x1F245, 'M', '〔打〕'),
    (0x1F246, 'M', '〔盗〕'),
    (0x1F247, 'M', '〔勝〕'),
    (0x1F248, 'M', '〔敗〕'),
    (0x1F249, 'X'),
    (0x1F250, 'M', '得'),
    (0x1F251, 'M', '可'),
    (0x1F252, 'X'),
    (0x1F260, 'V'),
    (0x1F266, 'X'),
    (0x1F300, 'V'),
    (0x1F6D8, 'X'),
    (0x1F6DC, 'V'),
    (0x1F6ED, 'X'),
    (0x1F6F0, 'V'),
    (0x1F6FD, 'X'),
    (0x1F700, 'V'),
    (0x1F777, 'X'),
    (0x1F77B, 'V'),
    (0x1F7DA, 'X'),
    (0x1F7E0, 'V'),
    (0x1F7EC, 'X'),
    (0x1F7F0, 'V'),
    (0x1F7F1, 'X'),
    (0x1F800, 'V'),
    (0x1F80C, 'X'),
    (0x1F810, 'V'),
    (0x1F848, 'X'),
    (0x1F850, 'V'),
    (0x1F85A, 'X'),
    (0x1F860, 'V'),
    (0x1F888, 'X'),
    (0x1F890, 'V'),
    (0x1F8AE, 'X'),
    (0x1F8B0, 'V'),
    (0x1F8B2, 'X'),
    (0x1F900, 'V'),
    (0x1FA54, 'X'),
    (0x1FA60, 'V'),
    (0x1FA6E, 'X'),
    (0x1FA70, 'V'),
    (0x1FA7D, 'X'),
    (0x1FA80, 'V'),
    (0x1FA89, 'X'),
    ]

def _seg_76() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x1FA90, 'V'),
    (0x1FABE, 'X'),
    (0x1FABF, 'V'),
    (0x1FAC6, 'X'),
    (0x1FACE, 'V'),
    (0x1FADC, 'X'),
    (0x1FAE0, 'V'),
    (0x1FAE9, 'X'),
    (0x1FAF0, 'V'),
    (0x1FAF9, 'X'),
    (0x1FB00, 'V'),
    (0x1FB93, 'X'),
    (0x1FB94, 'V'),
    (0x1FBCB, 'X'),
    (0x1FBF0, 'M', '0'),
    (0x1FBF1, 'M', '1'),
    (0x1FBF2, 'M', '2'),
    (0x1FBF3, 'M', '3'),
    (0x1FBF4, 'M', '4'),
    (0x1FBF5, 'M', '5'),
    (0x1FBF6, 'M', '6'),
    (0x1FBF7, 'M', '7'),
    (0x1FBF8, 'M', '8'),
    (0x1FBF9, 'M', '9'),
    (0x1FBFA, 'X'),
    (0x20000, 'V'),
    (0x2A6E0, 'X'),
    (0x2A700, 'V'),
    (0x2B73A, 'X'),
    (0x2B740, 'V'),
    (0x2B81E, 'X'),
    (0x2B820, 'V'),
    (0x2CEA2, 'X'),
    (0x2CEB0, 'V'),
    (0x2EBE1, 'X'),
    (0x2EBF0, 'V'),
    (0x2EE5E, 'X'),
    (0x2F800, 'M', '丽'),
    (0x2F801, 'M', '丸'),
    (0x2F802, 'M', '乁'),
    (0x2F803, 'M', '𠄢'),
    (0x2F804, 'M', '你'),
    (0x2F805, 'M', '侮'),
    (0x2F806, 'M', '侻'),
    (0x2F807, 'M', '倂'),
    (0x2F808, 'M', '偺'),
    (0x2F809, 'M', '備'),
    (0x2F80A, 'M', '僧'),
    (0x2F80B, 'M', '像'),
    (0x2F80C, 'M', '㒞'),
    (0x2F80D, 'M', '𠘺'),
    (0x2F80E, 'M', '免'),
    (0x2F80F, 'M', '兔'),
    (0x2F810, 'M', '兤'),
    (0x2F811, 'M', '具'),
    (0x2F812, 'M', '𠔜'),
    (0x2F813, 'M', '㒹'),
    (0x2F814, 'M', '內'),
    (0x2F815, 'M', '再'),
    (0x2F816, 'M', '𠕋'),
    (0x2F817, 'M', '冗'),
    (0x2F818, 'M', '冤'),
    (0x2F819, 'M', '仌'),
    (0x2F81A, 'M', '冬'),
    (0x2F81B, 'M', '况'),
    (0x2F81C, 'M', '𩇟'),
    (0x2F81D, 'M', '凵'),
    (0x2F81E, 'M', '刃'),
    (0x2F81F, 'M', '㓟'),
    (0x2F820, 'M', '刻'),
    (0x2F821, 'M', '剆'),
    (0x2F822, 'M', '割'),
    (0x2F823, 'M', '剷'),
    (0x2F824, 'M', '㔕'),
    (0x2F825, 'M', '勇'),
    (0x2F826, 'M', '勉'),
    (0x2F827, 'M', '勤'),
    (0x2F828, 'M', '勺'),
    (0x2F829, 'M', '包'),
    (0x2F82A, 'M', '匆'),
    (0x2F82B, 'M', '北'),
    (0x2F82C, 'M', '卉'),
    (0x2F82D, 'M', '卑'),
    (0x2F82E, 'M', '博'),
    (0x2F82F, 'M', '即'),
    (0x2F830, 'M', '卽'),
    (0x2F831, 'M', '卿'),
    (0x2F834, 'M', '𠨬'),
    (0x2F835, 'M', '灰'),
    (0x2F836, 'M', '及'),
    (0x2F837, 'M', '叟'),
    (0x2F838, 'M', '𠭣'),
    (0x2F839, 'M', '叫'),
    (0x2F83A, 'M', '叱'),
    (0x2F83B, 'M', '吆'),
    (0x2F83C, 'M', '咞'),
    (0x2F83D, 'M', '吸'),
    (0x2F83E, 'M', '呈'),
    (0x2F83F, 'M', '周'),
    (0x2F840, 'M', '咢'),
    ]

def _seg_77() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x2F841, 'M', '哶'),
    (0x2F842, 'M', '唐'),
    (0x2F843, 'M', '啓'),
    (0x2F844, 'M', '啣'),
    (0x2F845, 'M', '善'),
    (0x2F847, 'M', '喙'),
    (0x2F848, 'M', '喫'),
    (0x2F849, 'M', '喳'),
    (0x2F84A, 'M', '嗂'),
    (0x2F84B, 'M', '圖'),
    (0x2F84C, 'M', '嘆'),
    (0x2F84D, 'M', '圗'),
    (0x2F84E, 'M', '噑'),
    (0x2F84F, 'M', '噴'),
    (0x2F850, 'M', '切'),
    (0x2F851, 'M', '壮'),
    (0x2F852, 'M', '城'),
    (0x2F853, 'M', '埴'),
    (0x2F854, 'M', '堍'),
    (0x2F855, 'M', '型'),
    (0x2F856, 'M', '堲'),
    (0x2F857, 'M', '報'),
    (0x2F858, 'M', '墬'),
    (0x2F859, 'M', '𡓤'),
    (0x2F85A, 'M', '売'),
    (0x2F85B, 'M', '壷'),
    (0x2F85C, 'M', '夆'),
    (0x2F85D, 'M', '多'),
    (0x2F85E, 'M', '夢'),
    (0x2F85F, 'M', '奢'),
    (0x2F860, 'M', '𡚨'),
    (0x2F861, 'M', '𡛪'),
    (0x2F862, 'M', '姬'),
    (0x2F863, 'M', '娛'),
    (0x2F864, 'M', '娧'),
    (0x2F865, 'M', '姘'),
    (0x2F866, 'M', '婦'),
    (0x2F867, 'M', '㛮'),
    (0x2F868, 'X'),
    (0x2F869, 'M', '嬈'),
    (0x2F86A, 'M', '嬾'),
    (0x2F86C, 'M', '𡧈'),
    (0x2F86D, 'M', '寃'),
    (0x2F86E, 'M', '寘'),
    (0x2F86F, 'M', '寧'),
    (0x2F870, 'M', '寳'),
    (0x2F871, 'M', '𡬘'),
    (0x2F872, 'M', '寿'),
    (0x2F873, 'M', '将'),
    (0x2F874, 'X'),
    (0x2F875, 'M', '尢'),
    (0x2F876, 'M', '㞁'),
    (0x2F877, 'M', '屠'),
    (0x2F878, 'M', '屮'),
    (0x2F879, 'M', '峀'),
    (0x2F87A, 'M', '岍'),
    (0x2F87B, 'M', '𡷤'),
    (0x2F87C, 'M', '嵃'),
    (0x2F87D, 'M', '𡷦'),
    (0x2F87E, 'M', '嵮'),
    (0x2F87F, 'M', '嵫'),
    (0x2F880, 'M', '嵼'),
    (0x2F881, 'M', '巡'),
    (0x2F882, 'M', '巢'),
    (0x2F883, 'M', '㠯'),
    (0x2F884, 'M', '巽'),
    (0x2F885, 'M', '帨'),
    (0x2F886, 'M', '帽'),
    (0x2F887, 'M', '幩'),
    (0x2F888, 'M', '㡢'),
    (0x2F889, 'M', '𢆃'),
    (0x2F88A, 'M', '㡼'),
    (0x2F88B, 'M', '庰'),
    (0x2F88C, 'M', '庳'),
    (0x2F88D, 'M', '庶'),
    (0x2F88E, 'M', '廊'),
    (0x2F88F, 'M', '𪎒'),
    (0x2F890, 'M', '廾'),
    (0x2F891, 'M', '𢌱'),
    (0x2F893, 'M', '舁'),
    (0x2F894, 'M', '弢'),
    (0x2F896, 'M', '㣇'),
    (0x2F897, 'M', '𣊸'),
    (0x2F898, 'M', '𦇚'),
    (0x2F899, 'M', '形'),
    (0x2F89A, 'M', '彫'),
    (0x2F89B, 'M', '㣣'),
    (0x2F89C, 'M', '徚'),
    (0x2F89D, 'M', '忍'),
    (0x2F89E, 'M', '志'),
    (0x2F89F, 'M', '忹'),
    (0x2F8A0, 'M', '悁'),
    (0x2F8A1, 'M', '㤺'),
    (0x2F8A2, 'M', '㤜'),
    (0x2F8A3, 'M', '悔'),
    (0x2F8A4, 'M', '𢛔'),
    (0x2F8A5, 'M', '惇'),
    (0x2F8A6, 'M', '慈'),
    (0x2F8A7, 'M', '慌'),
    (0x2F8A8, 'M', '慎'),
    ]

def _seg_78() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x2F8A9, 'M', '慌'),
    (0x2F8AA, 'M', '慺'),
    (0x2F8AB, 'M', '憎'),
    (0x2F8AC, 'M', '憲'),
    (0x2F8AD, 'M', '憤'),
    (0x2F8AE, 'M', '憯'),
    (0x2F8AF, 'M', '懞'),
    (0x2F8B0, 'M', '懲'),
    (0x2F8B1, 'M', '懶'),
    (0x2F8B2, 'M', '成'),
    (0x2F8B3, 'M', '戛'),
    (0x2F8B4, 'M', '扝'),
    (0x2F8B5, 'M', '抱'),
    (0x2F8B6, 'M', '拔'),
    (0x2F8B7, 'M', '捐'),
    (0x2F8B8, 'M', '𢬌'),
    (0x2F8B9, 'M', '挽'),
    (0x2F8BA, 'M', '拼'),
    (0x2F8BB, 'M', '捨'),
    (0x2F8BC, 'M', '掃'),
    (0x2F8BD, 'M', '揤'),
    (0x2F8BE, 'M', '𢯱'),
    (0x2F8BF, 'M', '搢'),
    (0x2F8C0, 'M', '揅'),
    (0x2F8C1, 'M', '掩'),
    (0x2F8C2, 'M', '㨮'),
    (0x2F8C3, 'M', '摩'),
    (0x2F8C4, 'M', '摾'),
    (0x2F8C5, 'M', '撝'),
    (0x2F8C6, 'M', '摷'),
    (0x2F8C7, 'M', '㩬'),
    (0x2F8C8, 'M', '敏'),
    (0x2F8C9, 'M', '敬'),
    (0x2F8CA, 'M', '𣀊'),
    (0x2F8CB, 'M', '旣'),
    (0x2F8CC, 'M', '書'),
    (0x2F8CD, 'M', '晉'),
    (0x2F8CE, 'M', '㬙'),
    (0x2F8CF, 'M', '暑'),
    (0x2F8D0, 'M', '㬈'),
    (0x2F8D1, 'M', '㫤'),
    (0x2F8D2, 'M', '冒'),
    (0x2F8D3, 'M', '冕'),
    (0x2F8D4, 'M', '最'),
    (0x2F8D5, 'M', '暜'),
    (0x2F8D6, 'M', '肭'),
    (0x2F8D7, 'M', '䏙'),
    (0x2F8D8, 'M', '朗'),
    (0x2F8D9, 'M', '望'),
    (0x2F8DA, 'M', '朡'),
    (0x2F8DB, 'M', '杞'),
    (0x2F8DC, 'M', '杓'),
    (0x2F8DD, 'M', '𣏃'),
    (0x2F8DE, 'M', '㭉'),
    (0x2F8DF, 'M', '柺'),
    (0x2F8E0, 'M', '枅'),
    (0x2F8E1, 'M', '桒'),
    (0x2F8E2, 'M', '梅'),
    (0x2F8E3, 'M', '𣑭'),
    (0x2F8E4, 'M', '梎'),
    (0x2F8E5, 'M', '栟'),
    (0x2F8E6, 'M', '椔'),
    (0x2F8E7, 'M', '㮝'),
    (0x2F8E8, 'M', '楂'),
    (0x2F8E9, 'M', '榣'),
    (0x2F8EA, 'M', '槪'),
    (0x2F8EB, 'M', '檨'),
    (0x2F8EC, 'M', '𣚣'),
    (0x2F8ED, 'M', '櫛'),
    (0x2F8EE, 'M', '㰘'),
    (0x2F8EF, 'M', '次'),
    (0x2F8F0, 'M', '𣢧'),
    (0x2F8F1, 'M', '歔'),
    (0x2F8F2, 'M', '㱎'),
    (0x2F8F3, 'M', '歲'),
    (0x2F8F4, 'M', '殟'),
    (0x2F8F5, 'M', '殺'),
    (0x2F8F6, 'M', '殻'),
    (0x2F8F7, 'M', '𣪍'),
    (0x2F8F8, 'M', '𡴋'),
    (0x2F8F9, 'M', '𣫺'),
    (0x2F8FA, 'M', '汎'),
    (0x2F8FB, 'M', '𣲼'),
    (0x2F8FC, 'M', '沿'),
    (0x2F8FD, 'M', '泍'),
    (0x2F8FE, 'M', '汧'),
    (0x2F8FF, 'M', '洖'),
    (0x2F900, 'M', '派'),
    (0x2F901, 'M', '海'),
    (0x2F902, 'M', '流'),
    (0x2F903, 'M', '浩'),
    (0x2F904, 'M', '浸'),
    (0x2F905, 'M', '涅'),
    (0x2F906, 'M', '𣴞'),
    (0x2F907, 'M', '洴'),
    (0x2F908, 'M', '港'),
    (0x2F909, 'M', '湮'),
    (0x2F90A, 'M', '㴳'),
    (0x2F90B, 'M', '滋'),
    (0x2F90C, 'M', '滇'),
    ]

def _seg_79() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x2F90D, 'M', '𣻑'),
    (0x2F90E, 'M', '淹'),
    (0x2F90F, 'M', '潮'),
    (0x2F910, 'M', '𣽞'),
    (0x2F911, 'M', '𣾎'),
    (0x2F912, 'M', '濆'),
    (0x2F913, 'M', '瀹'),
    (0x2F914, 'M', '瀞'),
    (0x2F915, 'M', '瀛'),
    (0x2F916, 'M', '㶖'),
    (0x2F917, 'M', '灊'),
    (0x2F918, 'M', '災'),
    (0x2F919, 'M', '灷'),
    (0x2F91A, 'M', '炭'),
    (0x2F91B, 'M', '𠔥'),
    (0x2F91C, 'M', '煅'),
    (0x2F91D, 'M', '𤉣'),
    (0x2F91E, 'M', '熜'),
    (0x2F91F, 'X'),
    (0x2F920, 'M', '爨'),
    (0x2F921, 'M', '爵'),
    (0x2F922, 'M', '牐'),
    (0x2F923, 'M', '𤘈'),
    (0x2F924, 'M', '犀'),
    (0x2F925, 'M', '犕'),
    (0x2F926, 'M', '𤜵'),
    (0x2F927, 'M', '𤠔'),
    (0x2F928, 'M', '獺'),
    (0x2F929, 'M', '王'),
    (0x2F92A, 'M', '㺬'),
    (0x2F92B, 'M', '玥'),
    (0x2F92C, 'M', '㺸'),
    (0x2F92E, 'M', '瑇'),
    (0x2F92F, 'M', '瑜'),
    (0x2F930, 'M', '瑱'),
    (0x2F931, 'M', '璅'),
    (0x2F932, 'M', '瓊'),
    (0x2F933, 'M', '㼛'),
    (0x2F934, 'M', '甤'),
    (0x2F935, 'M', '𤰶'),
    (0x2F936, 'M', '甾'),
    (0x2F937, 'M', '𤲒'),
    (0x2F938, 'M', '異'),
    (0x2F939, 'M', '𢆟'),
    (0x2F93A, 'M', '瘐'),
    (0x2F93B, 'M', '𤾡'),
    (0x2F93C, 'M', '𤾸'),
    (0x2F93D, 'M', '𥁄'),
    (0x2F93E, 'M', '㿼'),
    (0x2F93F, 'M', '䀈'),
    (0x2F940, 'M', '直'),
    (0x2F941, 'M', '𥃳'),
    (0x2F942, 'M', '𥃲'),
    (0x2F943, 'M', '𥄙'),
    (0x2F944, 'M', '𥄳'),
    (0x2F945, 'M', '眞'),
    (0x2F946, 'M', '真'),
    (0x2F948, 'M', '睊'),
    (0x2F949, 'M', '䀹'),
    (0x2F94A, 'M', '瞋'),
    (0x2F94B, 'M', '䁆'),
    (0x2F94C, 'M', '䂖'),
    (0x2F94D, 'M', '𥐝'),
    (0x2F94E, 'M', '硎'),
    (0x2F94F, 'M', '碌'),
    (0x2F950, 'M', '磌'),
    (0x2F951, 'M', '䃣'),
    (0x2F952, 'M', '𥘦'),
    (0x2F953, 'M', '祖'),
    (0x2F954, 'M', '𥚚'),
    (0x2F955, 'M', '𥛅'),
    (0x2F956, 'M', '福'),
    (0x2F957, 'M', '秫'),
    (0x2F958, 'M', '䄯'),
    (0x2F959, 'M', '穀'),
    (0x2F95A, 'M', '穊'),
    (0x2F95B, 'M', '穏'),
    (0x2F95C, 'M', '𥥼'),
    (0x2F95D, 'M', '𥪧'),
    (0x2F95F, 'X'),
    (0x2F960, 'M', '䈂'),
    (0x2F961, 'M', '𥮫'),
    (0x2F962, 'M', '篆'),
    (0x2F963, 'M', '築'),
    (0x2F964, 'M', '䈧'),
    (0x2F965, 'M', '𥲀'),
    (0x2F966, 'M', '糒'),
    (0x2F967, 'M', '䊠'),
    (0x2F968, 'M', '糨'),
    (0x2F969, 'M', '糣'),
    (0x2F96A, 'M', '紀'),
    (0x2F96B, 'M', '𥾆'),
    (0x2F96C, 'M', '絣'),
    (0x2F96D, 'M', '䌁'),
    (0x2F96E, 'M', '緇'),
    (0x2F96F, 'M', '縂'),
    (0x2F970, 'M', '繅'),
    (0x2F971, 'M', '䌴'),
    (0x2F972, 'M', '𦈨'),
    (0x2F973, 'M', '𦉇'),
    ]

def _seg_80() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x2F974, 'M', '䍙'),
    (0x2F975, 'M', '𦋙'),
    (0x2F976, 'M', '罺'),
    (0x2F977, 'M', '𦌾'),
    (0x2F978, 'M', '羕'),
    (0x2F979, 'M', '翺'),
    (0x2F97A, 'M', '者'),
    (0x2F97B, 'M', '𦓚'),
    (0x2F97C, 'M', '𦔣'),
    (0x2F97D, 'M', '聠'),
    (0x2F97E, 'M', '𦖨'),
    (0x2F97F, 'M', '聰'),
    (0x2F980, 'M', '𣍟'),
    (0x2F981, 'M', '䏕'),
    (0x2F982, 'M', '育'),
    (0x2F983, 'M', '脃'),
    (0x2F984, 'M', '䐋'),
    (0x2F985, 'M', '脾'),
    (0x2F986, 'M', '媵'),
    (0x2F987, 'M', '𦞧'),
    (0x2F988, 'M', '𦞵'),
    (0x2F989, 'M', '𣎓'),
    (0x2F98A, 'M', '𣎜'),
    (0x2F98B, 'M', '舁'),
    (0x2F98C, 'M', '舄'),
    (0x2F98D, 'M', '辞'),
    (0x2F98E, 'M', '䑫'),
    (0x2F98F, 'M', '芑'),
    (0x2F990, 'M', '芋'),
    (0x2F991, 'M', '芝'),
    (0x2F992, 'M', '劳'),
    (0x2F993, 'M', '花'),
    (0x2F994, 'M', '芳'),
    (0x2F995, 'M', '芽'),
    (0x2F996, 'M', '苦'),
    (0x2F997, 'M', '𦬼'),
    (0x2F998, 'M', '若'),
    (0x2F999, 'M', '茝'),
    (0x2F99A, 'M', '荣'),
    (0x2F99B, 'M', '莭'),
    (0x2F99C, 'M', '茣'),
    (0x2F99D, 'M', '莽'),
    (0x2F99E, 'M', '菧'),
    (0x2F99F, 'M', '著'),
    (0x2F9A0, 'M', '荓'),
    (0x2F9A1, 'M', '菊'),
    (0x2F9A2, 'M', '菌'),
    (0x2F9A3, 'M', '菜'),
    (0x2F9A4, 'M', '𦰶'),
    (0x2F9A5, 'M', '𦵫'),
    (0x2F9A6, 'M', '𦳕'),
    (0x2F9A7, 'M', '䔫'),
    (0x2F9A8, 'M', '蓱'),
    (0x2F9A9, 'M', '蓳'),
    (0x2F9AA, 'M', '蔖'),
    (0x2F9AB, 'M', '𧏊'),
    (0x2F9AC, 'M', '蕤'),
    (0x2F9AD, 'M', '𦼬'),
    (0x2F9AE, 'M', '䕝'),
    (0x2F9AF, 'M', '䕡'),
    (0x2F9B0, 'M', '𦾱'),
    (0x2F9B1, 'M', '𧃒'),
    (0x2F9B2, 'M', '䕫'),
    (0x2F9B3, 'M', '虐'),
    (0x2F9B4, 'M', '虜'),
    (0x2F9B5, 'M', '虧'),
    (0x2F9B6, 'M', '虩'),
    (0x2F9B7, 'M', '蚩'),
    (0x2F9B8, 'M', '蚈'),
    (0x2F9B9, 'M', '蜎'),
    (0x2F9BA, 'M', '蛢'),
    (0x2F9BB, 'M', '蝹'),
    (0x2F9BC, 'M', '蜨'),
    (0x2F9BD, 'M', '蝫'),
    (0x2F9BE, 'M', '螆'),
    (0x2F9BF, 'X'),
    (0x2F9C0, 'M', '蟡'),
    (0x2F9C1, 'M', '蠁'),
    (0x2F9C2, 'M', '䗹'),
    (0x2F9C3, 'M', '衠'),
    (0x2F9C4, 'M', '衣'),
    (0x2F9C5, 'M', '𧙧'),
    (0x2F9C6, 'M', '裗'),
    (0x2F9C7, 'M', '裞'),
    (0x2F9C8, 'M', '䘵'),
    (0x2F9C9, 'M', '裺'),
    (0x2F9CA, 'M', '㒻'),
    (0x2F9CB, 'M', '𧢮'),
    (0x2F9CC, 'M', '𧥦'),
    (0x2F9CD, 'M', '䚾'),
    (0x2F9CE, 'M', '䛇'),
    (0x2F9CF, 'M', '誠'),
    (0x2F9D0, 'M', '諭'),
    (0x2F9D1, 'M', '變'),
    (0x2F9D2, 'M', '豕'),
    (0x2F9D3, 'M', '𧲨'),
    (0x2F9D4, 'M', '貫'),
    (0x2F9D5, 'M', '賁'),
    (0x2F9D6, 'M', '贛'),
    (0x2F9D7, 'M', '起'),
    ]

def _seg_81() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
    return [
    (0x2F9D8, 'M', '𧼯'),
    (0x2F9D9, 'M', '𠠄'),
    (0x2F9DA, 'M', '跋'),
    (0x2F9DB, 'M', '趼'),
    (0x2F9DC, 'M', '跰'),
    (0x2F9DD, 'M', '𠣞'),
    (0x2F9DE, 'M', '軔'),
    (0x2F9DF, 'M', '輸'),
    (0x2F9E0, 'M', '𨗒'),
    (0x2F9E1, 'M', '𨗭'),
    (0x2F9E2, 'M', '邔'),
    (0x2F9E3, 'M', '郱'),
    (0x2F9E4, 'M', '鄑'),
    (0x2F9E5, 'M', '𨜮'),
    (0x2F9E6, 'M', '鄛'),
    (0x2F9E7, 'M', '鈸'),
    (0x2F9E8, 'M', '鋗'),
    (0x2F9E9, 'M', '鋘'),
    (0x2F9EA, 'M', '鉼'),
    (0x2F9EB, 'M', '鏹'),
    (0x2F9EC, 'M', '鐕'),
    (0x2F9ED, 'M', '𨯺'),
    (0x2F9EE, 'M', '開'),
    (0x2F9EF, 'M', '䦕'),
    (0x2F9F0, 'M', '閷'),
    (0x2F9F1, 'M', '𨵷'),
    (0x2F9F2, 'M', '䧦'),
    (0x2F9F3, 'M', '雃'),
    (0x2F9F4, 'M', '嶲'),
    (0x2F9F5, 'M', '霣'),
    (0x2F9F6, 'M', '𩅅'),
    (0x2F9F7, 'M', '𩈚'),
    (0x2F9F8, 'M', '䩮'),
    (0x2F9F9, 'M', '䩶'),
    (0x2F9FA, 'M', '韠'),
    (0x2F9FB, 'M', '𩐊'),
    (0x2F9FC, 'M', '䪲'),
    (0x2F9FD, 'M', '𩒖'),
    (0x2F9FE, 'M', '頋'),
    (0x2FA00, 'M', '頩'),
    (0x2FA01, 'M', '𩖶'),
    (0x2FA02, 'M', '飢'),
    (0x2FA03, 'M', '䬳'),
    (0x2FA04, 'M', '餩'),
    (0x2FA05, 'M', '馧'),
    (0x2FA06, 'M', '駂'),
    (0x2FA07, 'M', '駾'),
    (0x2FA08, 'M', '䯎'),
    (0x2FA09, 'M', '𩬰'),
    (0x2FA0A, 'M', '鬒'),
    (0x2FA0B, 'M', '鱀'),
    (0x2FA0C, 'M', '鳽'),
    (0x2FA0D, 'M', '䳎'),
    (0x2FA0E, 'M', '䳭'),
    (0x2FA0F, 'M', '鵧'),
    (0x2FA10, 'M', '𪃎'),
    (0x2FA11, 'M', '䳸'),
    (0x2FA12, 'M', '𪄅'),
    (0x2FA13, 'M', '𪈎'),
    (0x2FA14, 'M', '𪊑'),
    (0x2FA15, 'M', '麻'),
    (0x2FA16, 'M', '䵖'),
    (0x2FA17, 'M', '黹'),
    (0x2FA18, 'M', '黾'),
    (0x2FA19, 'M', '鼅'),
    (0x2FA1A, 'M', '鼏'),
    (0x2FA1B, 'M', '鼖'),
    (0x2FA1C, 'M', '鼻'),
    (0x2FA1D, 'M', '𪘀'),
    (0x2FA1E, 'X'),
    (0x30000, 'V'),
    (0x3134B, 'X'),
    (0x31350, 'V'),
    (0x323B0, 'X'),
    (0xE0100, 'I'),
    (0xE01F0, 'X'),
    ]

uts46data = tuple(
    _seg_0()
    + _seg_1()
    + _seg_2()
    + _seg_3()
    + _seg_4()
    + _seg_5()
    + _seg_6()
    + _seg_7()
    + _seg_8()
    + _seg_9()
    + _seg_10()
    + _seg_11()
    + _seg_12()
    + _seg_13()
    + _seg_14()
    + _seg_15()
    + _seg_16()
    + _seg_17()
    + _seg_18()
    + _seg_19()
    + _seg_20()
    + _seg_21()
    + _seg_22()
    + _seg_23()
    + _seg_24()
    + _seg_25()
    + _seg_26()
    + _seg_27()
    + _seg_28()
    + _seg_29()
    + _seg_30()
    + _seg_31()
    + _seg_32()
    + _seg_33()
    + _seg_34()
    + _seg_35()
    + _seg_36()
    + _seg_37()
    + _seg_38()
    + _seg_39()
    + _seg_40()
    + _seg_41()
    + _seg_42()
    + _seg_43()
    + _seg_44()
    + _seg_45()
    + _seg_46()
    + _seg_47()
    + _seg_48()
    + _seg_49()
    + _seg_50()
    + _seg_51()
    + _seg_52()
    + _seg_53()
    + _seg_54()
    + _seg_55()
    + _seg_56()
    + _seg_57()
    + _seg_58()
    + _seg_59()
    + _seg_60()
    + _seg_61()
    + _seg_62()
    + _seg_63()
    + _seg_64()
    + _seg_65()
    + _seg_66()
    + _seg_67()
    + _seg_68()
    + _seg_69()
    + _seg_70()
    + _seg_71()
    + _seg_72()
    + _seg_73()
    + _seg_74()
    + _seg_75()
    + _seg_76()
    + _seg_77()
    + _seg_78()
    + _seg_79()
    + _seg_80()
    + _seg_81()
)  # type: Tuple[Union[Tuple[int, str], Tuple[int, str, str]], ...]
8,599 lines•201.7 KB
python
.venv/Lib/site-packages/pip/_vendor/distlib/wheel.py
Raw Download
Find: Go to:
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013-2023 Vinay Sajip.
# Licensed to the Python Software Foundation under a contributor agreement.
# See LICENSE.txt and CONTRIBUTORS.txt.
#
from __future__ import unicode_literals

import base64
import codecs
import datetime
from email import message_from_file
import hashlib
import json
import logging
import os
import posixpath
import re
import shutil
import sys
import tempfile
import zipfile

from . import __version__, DistlibException
from .compat import sysconfig, ZipFile, fsdecode, text_type, filter
from .database import InstalledDistribution
from .metadata import Metadata, WHEEL_METADATA_FILENAME, LEGACY_METADATA_FILENAME
from .util import (FileOperator, convert_path, CSVReader, CSVWriter, Cache, cached_property, get_cache_base,
                   read_exports, tempdir, get_platform)
from .version import NormalizedVersion, UnsupportedVersionError

logger = logging.getLogger(__name__)

cache = None  # created when needed

if hasattr(sys, 'pypy_version_info'):  # pragma: no cover
    IMP_PREFIX = 'pp'
elif sys.platform.startswith('java'):  # pragma: no cover
    IMP_PREFIX = 'jy'
elif sys.platform == 'cli':  # pragma: no cover
    IMP_PREFIX = 'ip'
else:
    IMP_PREFIX = 'cp'

VER_SUFFIX = sysconfig.get_config_var('py_version_nodot')
if not VER_SUFFIX:  # pragma: no cover
    VER_SUFFIX = '%s%s' % sys.version_info[:2]
PYVER = 'py' + VER_SUFFIX
IMPVER = IMP_PREFIX + VER_SUFFIX

ARCH = get_platform().replace('-', '_').replace('.', '_')

ABI = sysconfig.get_config_var('SOABI')
if ABI and ABI.startswith('cpython-'):
    ABI = ABI.replace('cpython-', 'cp').split('-')[0]
else:

    def _derive_abi():
        parts = ['cp', VER_SUFFIX]
        if sysconfig.get_config_var('Py_DEBUG'):
            parts.append('d')
        if IMP_PREFIX == 'cp':
            vi = sys.version_info[:2]
            if vi < (3, 8):
                wpm = sysconfig.get_config_var('WITH_PYMALLOC')
                if wpm is None:
                    wpm = True
                if wpm:
                    parts.append('m')
                if vi < (3, 3):
                    us = sysconfig.get_config_var('Py_UNICODE_SIZE')
                    if us == 4 or (us is None and sys.maxunicode == 0x10FFFF):
                        parts.append('u')
        return ''.join(parts)

    ABI = _derive_abi()
    del _derive_abi

FILENAME_RE = re.compile(
    r'''
(?P<nm>[^-]+)
-(?P<vn>\d+[^-]*)
(-(?P<bn>\d+[^-]*))?
-(?P<py>\w+\d+(\.\w+\d+)*)
-(?P<bi>\w+)
-(?P<ar>\w+(\.\w+)*)
\.whl$
''', re.IGNORECASE | re.VERBOSE)

NAME_VERSION_RE = re.compile(r'''
(?P<nm>[^-]+)
-(?P<vn>\d+[^-]*)
(-(?P<bn>\d+[^-]*))?$
''', re.IGNORECASE | re.VERBOSE)

SHEBANG_RE = re.compile(br'\s*#![^\r\n]*')
SHEBANG_DETAIL_RE = re.compile(br'^(\s*#!("[^"]+"|\S+))\s+(.*)$')
SHEBANG_PYTHON = b'#!python'
SHEBANG_PYTHONW = b'#!pythonw'

if os.sep == '/':
    to_posix = lambda o: o
else:
    to_posix = lambda o: o.replace(os.sep, '/')

if sys.version_info[0] < 3:
    import imp
else:
    imp = None
    import importlib.machinery
    import importlib.util


def _get_suffixes():
    if imp:
        return [s[0] for s in imp.get_suffixes()]
    else:
        return importlib.machinery.EXTENSION_SUFFIXES


def _load_dynamic(name, path):
    # https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
    if imp:
        return imp.load_dynamic(name, path)
    else:
        spec = importlib.util.spec_from_file_location(name, path)
        module = importlib.util.module_from_spec(spec)
        sys.modules[name] = module
        spec.loader.exec_module(module)
        return module


class Mounter(object):

    def __init__(self):
        self.impure_wheels = {}
        self.libs = {}

    def add(self, pathname, extensions):
        self.impure_wheels[pathname] = extensions
        self.libs.update(extensions)

    def remove(self, pathname):
        extensions = self.impure_wheels.pop(pathname)
        for k, v in extensions:
            if k in self.libs:
                del self.libs[k]

    def find_module(self, fullname, path=None):
        if fullname in self.libs:
            result = self
        else:
            result = None
        return result

    def load_module(self, fullname):
        if fullname in sys.modules:
            result = sys.modules[fullname]
        else:
            if fullname not in self.libs:
                raise ImportError('unable to find extension for %s' % fullname)
            result = _load_dynamic(fullname, self.libs[fullname])
            result.__loader__ = self
            parts = fullname.rsplit('.', 1)
            if len(parts) > 1:
                result.__package__ = parts[0]
        return result


_hook = Mounter()


class Wheel(object):
    """
    Class to build and install from Wheel files (PEP 427).
    """

    wheel_version = (1, 1)
    hash_kind = 'sha256'

    def __init__(self, filename=None, sign=False, verify=False):
        """
        Initialise an instance using a (valid) filename.
        """
        self.sign = sign
        self.should_verify = verify
        self.buildver = ''
        self.pyver = [PYVER]
        self.abi = ['none']
        self.arch = ['any']
        self.dirname = os.getcwd()
        if filename is None:
            self.name = 'dummy'
            self.version = '0.1'
            self._filename = self.filename
        else:
            m = NAME_VERSION_RE.match(filename)
            if m:
                info = m.groupdict('')
                self.name = info['nm']
                # Reinstate the local version separator
                self.version = info['vn'].replace('_', '-')
                self.buildver = info['bn']
                self._filename = self.filename
            else:
                dirname, filename = os.path.split(filename)
                m = FILENAME_RE.match(filename)
                if not m:
                    raise DistlibException('Invalid name or '
                                           'filename: %r' % filename)
                if dirname:
                    self.dirname = os.path.abspath(dirname)
                self._filename = filename
                info = m.groupdict('')
                self.name = info['nm']
                self.version = info['vn']
                self.buildver = info['bn']
                self.pyver = info['py'].split('.')
                self.abi = info['bi'].split('.')
                self.arch = info['ar'].split('.')

    @property
    def filename(self):
        """
        Build and return a filename from the various components.
        """
        if self.buildver:
            buildver = '-' + self.buildver
        else:
            buildver = ''
        pyver = '.'.join(self.pyver)
        abi = '.'.join(self.abi)
        arch = '.'.join(self.arch)
        # replace - with _ as a local version separator
        version = self.version.replace('-', '_')
        return '%s-%s%s-%s-%s-%s.whl' % (self.name, version, buildver, pyver, abi, arch)

    @property
    def exists(self):
        path = os.path.join(self.dirname, self.filename)
        return os.path.isfile(path)

    @property
    def tags(self):
        for pyver in self.pyver:
            for abi in self.abi:
                for arch in self.arch:
                    yield pyver, abi, arch

    @cached_property
    def metadata(self):
        pathname = os.path.join(self.dirname, self.filename)
        name_ver = '%s-%s' % (self.name, self.version)
        info_dir = '%s.dist-info' % name_ver
        wrapper = codecs.getreader('utf-8')
        with ZipFile(pathname, 'r') as zf:
            self.get_wheel_metadata(zf)
            # wv = wheel_metadata['Wheel-Version'].split('.', 1)
            # file_version = tuple([int(i) for i in wv])
            # if file_version < (1, 1):
            # fns = [WHEEL_METADATA_FILENAME, METADATA_FILENAME,
            # LEGACY_METADATA_FILENAME]
            # else:
            # fns = [WHEEL_METADATA_FILENAME, METADATA_FILENAME]
            fns = [WHEEL_METADATA_FILENAME, LEGACY_METADATA_FILENAME]
            result = None
            for fn in fns:
                try:
                    metadata_filename = posixpath.join(info_dir, fn)
                    with zf.open(metadata_filename) as bf:
                        wf = wrapper(bf)
                        result = Metadata(fileobj=wf)
                        if result:
                            break
                except KeyError:
                    pass
            if not result:
                raise ValueError('Invalid wheel, because metadata is '
                                 'missing: looked in %s' % ', '.join(fns))
        return result

    def get_wheel_metadata(self, zf):
        name_ver = '%s-%s' % (self.name, self.version)
        info_dir = '%s.dist-info' % name_ver
        metadata_filename = posixpath.join(info_dir, 'WHEEL')
        with zf.open(metadata_filename) as bf:
            wf = codecs.getreader('utf-8')(bf)
            message = message_from_file(wf)
        return dict(message)

    @cached_property
    def info(self):
        pathname = os.path.join(self.dirname, self.filename)
        with ZipFile(pathname, 'r') as zf:
            result = self.get_wheel_metadata(zf)
        return result

    def process_shebang(self, data):
        m = SHEBANG_RE.match(data)
        if m:
            end = m.end()
            shebang, data_after_shebang = data[:end], data[end:]
            # Preserve any arguments after the interpreter
            if b'pythonw' in shebang.lower():
                shebang_python = SHEBANG_PYTHONW
            else:
                shebang_python = SHEBANG_PYTHON
            m = SHEBANG_DETAIL_RE.match(shebang)
            if m:
                args = b' ' + m.groups()[-1]
            else:
                args = b''
            shebang = shebang_python + args
            data = shebang + data_after_shebang
        else:
            cr = data.find(b'\r')
            lf = data.find(b'\n')
            if cr < 0 or cr > lf:
                term = b'\n'
            else:
                if data[cr:cr + 2] == b'\r\n':
                    term = b'\r\n'
                else:
                    term = b'\r'
            data = SHEBANG_PYTHON + term + data
        return data

    def get_hash(self, data, hash_kind=None):
        if hash_kind is None:
            hash_kind = self.hash_kind
        try:
            hasher = getattr(hashlib, hash_kind)
        except AttributeError:
            raise DistlibException('Unsupported hash algorithm: %r' % hash_kind)
        result = hasher(data).digest()
        result = base64.urlsafe_b64encode(result).rstrip(b'=').decode('ascii')
        return hash_kind, result

    def write_record(self, records, record_path, archive_record_path):
        records = list(records)  # make a copy, as mutated
        records.append((archive_record_path, '', ''))
        with CSVWriter(record_path) as writer:
            for row in records:
                writer.writerow(row)

    def write_records(self, info, libdir, archive_paths):
        records = []
        distinfo, info_dir = info
        # hasher = getattr(hashlib, self.hash_kind)
        for ap, p in archive_paths:
            with open(p, 'rb') as f:
                data = f.read()
            digest = '%s=%s' % self.get_hash(data)
            size = os.path.getsize(p)
            records.append((ap, digest, size))

        p = os.path.join(distinfo, 'RECORD')
        ap = to_posix(os.path.join(info_dir, 'RECORD'))
        self.write_record(records, p, ap)
        archive_paths.append((ap, p))

    def build_zip(self, pathname, archive_paths):
        with ZipFile(pathname, 'w', zipfile.ZIP_DEFLATED) as zf:
            for ap, p in archive_paths:
                logger.debug('Wrote %s to %s in wheel', p, ap)
                zf.write(p, ap)

    def build(self, paths, tags=None, wheel_version=None):
        """
        Build a wheel from files in specified paths, and use any specified tags
        when determining the name of the wheel.
        """
        if tags is None:
            tags = {}

        libkey = list(filter(lambda o: o in paths, ('purelib', 'platlib')))[0]
        if libkey == 'platlib':
            is_pure = 'false'
            default_pyver = [IMPVER]
            default_abi = [ABI]
            default_arch = [ARCH]
        else:
            is_pure = 'true'
            default_pyver = [PYVER]
            default_abi = ['none']
            default_arch = ['any']

        self.pyver = tags.get('pyver', default_pyver)
        self.abi = tags.get('abi', default_abi)
        self.arch = tags.get('arch', default_arch)

        libdir = paths[libkey]

        name_ver = '%s-%s' % (self.name, self.version)
        data_dir = '%s.data' % name_ver
        info_dir = '%s.dist-info' % name_ver

        archive_paths = []

        # First, stuff which is not in site-packages
        for key in ('data', 'headers', 'scripts'):
            if key not in paths:
                continue
            path = paths[key]
            if os.path.isdir(path):
                for root, dirs, files in os.walk(path):
                    for fn in files:
                        p = fsdecode(os.path.join(root, fn))
                        rp = os.path.relpath(p, path)
                        ap = to_posix(os.path.join(data_dir, key, rp))
                        archive_paths.append((ap, p))
                        if key == 'scripts' and not p.endswith('.exe'):
                            with open(p, 'rb') as f:
                                data = f.read()
                            data = self.process_shebang(data)
                            with open(p, 'wb') as f:
                                f.write(data)

        # Now, stuff which is in site-packages, other than the
        # distinfo stuff.
        path = libdir
        distinfo = None
        for root, dirs, files in os.walk(path):
            if root == path:
                # At the top level only, save distinfo for later
                # and skip it for now
                for i, dn in enumerate(dirs):
                    dn = fsdecode(dn)
                    if dn.endswith('.dist-info'):
                        distinfo = os.path.join(root, dn)
                        del dirs[i]
                        break
                assert distinfo, '.dist-info directory expected, not found'

            for fn in files:
                # comment out next suite to leave .pyc files in
                if fsdecode(fn).endswith(('.pyc', '.pyo')):
                    continue
                p = os.path.join(root, fn)
                rp = to_posix(os.path.relpath(p, path))
                archive_paths.append((rp, p))

        # Now distinfo. Assumed to be flat, i.e. os.listdir is enough.
        files = os.listdir(distinfo)
        for fn in files:
            if fn not in ('RECORD', 'INSTALLER', 'SHARED', 'WHEEL'):
                p = fsdecode(os.path.join(distinfo, fn))
                ap = to_posix(os.path.join(info_dir, fn))
                archive_paths.append((ap, p))

        wheel_metadata = [
            'Wheel-Version: %d.%d' % (wheel_version or self.wheel_version),
            'Generator: distlib %s' % __version__,
            'Root-Is-Purelib: %s' % is_pure,
        ]
        for pyver, abi, arch in self.tags:
            wheel_metadata.append('Tag: %s-%s-%s' % (pyver, abi, arch))
        p = os.path.join(distinfo, 'WHEEL')
        with open(p, 'w') as f:
            f.write('\n'.join(wheel_metadata))
        ap = to_posix(os.path.join(info_dir, 'WHEEL'))
        archive_paths.append((ap, p))

        # sort the entries by archive path. Not needed by any spec, but it
        # keeps the archive listing and RECORD tidier than they would otherwise
        # be. Use the number of path segments to keep directory entries together,
        # and keep the dist-info stuff at the end.
        def sorter(t):
            ap = t[0]
            n = ap.count('/')
            if '.dist-info' in ap:
                n += 10000
            return (n, ap)

        archive_paths = sorted(archive_paths, key=sorter)

        # Now, at last, RECORD.
        # Paths in here are archive paths - nothing else makes sense.
        self.write_records((distinfo, info_dir), libdir, archive_paths)
        # Now, ready to build the zip file
        pathname = os.path.join(self.dirname, self.filename)
        self.build_zip(pathname, archive_paths)
        return pathname

    def skip_entry(self, arcname):
        """
        Determine whether an archive entry should be skipped when verifying
        or installing.
        """
        # The signature file won't be in RECORD,
        # and we  don't currently don't do anything with it
        # We also skip directories, as they won't be in RECORD
        # either. See:
        #
        # https://github.com/pypa/wheel/issues/294
        # https://github.com/pypa/wheel/issues/287
        # https://github.com/pypa/wheel/pull/289
        #
        return arcname.endswith(('/', '/RECORD.jws'))

    def install(self, paths, maker, **kwargs):
        """
        Install a wheel to the specified paths. If kwarg ``warner`` is
        specified, it should be a callable, which will be called with two
        tuples indicating the wheel version of this software and the wheel
        version in the file, if there is a discrepancy in the versions.
        This can be used to issue any warnings to raise any exceptions.
        If kwarg ``lib_only`` is True, only the purelib/platlib files are
        installed, and the headers, scripts, data and dist-info metadata are
        not written. If kwarg ``bytecode_hashed_invalidation`` is True, written
        bytecode will try to use file-hash based invalidation (PEP-552) on
        supported interpreter versions (CPython 3.7+).

        The return value is a :class:`InstalledDistribution` instance unless
        ``options.lib_only`` is True, in which case the return value is ``None``.
        """

        dry_run = maker.dry_run
        warner = kwargs.get('warner')
        lib_only = kwargs.get('lib_only', False)
        bc_hashed_invalidation = kwargs.get('bytecode_hashed_invalidation', False)

        pathname = os.path.join(self.dirname, self.filename)
        name_ver = '%s-%s' % (self.name, self.version)
        data_dir = '%s.data' % name_ver
        info_dir = '%s.dist-info' % name_ver

        metadata_name = posixpath.join(info_dir, LEGACY_METADATA_FILENAME)
        wheel_metadata_name = posixpath.join(info_dir, 'WHEEL')
        record_name = posixpath.join(info_dir, 'RECORD')

        wrapper = codecs.getreader('utf-8')

        with ZipFile(pathname, 'r') as zf:
            with zf.open(wheel_metadata_name) as bwf:
                wf = wrapper(bwf)
                message = message_from_file(wf)
            wv = message['Wheel-Version'].split('.', 1)
            file_version = tuple([int(i) for i in wv])
            if (file_version != self.wheel_version) and warner:
                warner(self.wheel_version, file_version)

            if message['Root-Is-Purelib'] == 'true':
                libdir = paths['purelib']
            else:
                libdir = paths['platlib']

            records = {}
            with zf.open(record_name) as bf:
                with CSVReader(stream=bf) as reader:
                    for row in reader:
                        p = row[0]
                        records[p] = row

            data_pfx = posixpath.join(data_dir, '')
            info_pfx = posixpath.join(info_dir, '')
            script_pfx = posixpath.join(data_dir, 'scripts', '')

            # make a new instance rather than a copy of maker's,
            # as we mutate it
            fileop = FileOperator(dry_run=dry_run)
            fileop.record = True  # so we can rollback if needed

            bc = not sys.dont_write_bytecode  # Double negatives. Lovely!

            outfiles = []  # for RECORD writing

            # for script copying/shebang processing
            workdir = tempfile.mkdtemp()
            # set target dir later
            # we default add_launchers to False, as the
            # Python Launcher should be used instead
            maker.source_dir = workdir
            maker.target_dir = None
            try:
                for zinfo in zf.infolist():
                    arcname = zinfo.filename
                    if isinstance(arcname, text_type):
                        u_arcname = arcname
                    else:
                        u_arcname = arcname.decode('utf-8')
                    if self.skip_entry(u_arcname):
                        continue
                    row = records[u_arcname]
                    if row[2] and str(zinfo.file_size) != row[2]:
                        raise DistlibException('size mismatch for '
                                               '%s' % u_arcname)
                    if row[1]:
                        kind, value = row[1].split('=', 1)
                        with zf.open(arcname) as bf:
                            data = bf.read()
                        _, digest = self.get_hash(data, kind)
                        if digest != value:
                            raise DistlibException('digest mismatch for '
                                                   '%s' % arcname)

                    if lib_only and u_arcname.startswith((info_pfx, data_pfx)):
                        logger.debug('lib_only: skipping %s', u_arcname)
                        continue
                    is_script = (u_arcname.startswith(script_pfx) and not u_arcname.endswith('.exe'))

                    if u_arcname.startswith(data_pfx):
                        _, where, rp = u_arcname.split('/', 2)
                        outfile = os.path.join(paths[where], convert_path(rp))
                    else:
                        # meant for site-packages.
                        if u_arcname in (wheel_metadata_name, record_name):
                            continue
                        outfile = os.path.join(libdir, convert_path(u_arcname))
                    if not is_script:
                        with zf.open(arcname) as bf:
                            fileop.copy_stream(bf, outfile)
                        # Issue #147: permission bits aren't preserved. Using
                        # zf.extract(zinfo, libdir) should have worked, but didn't,
                        # see https://www.thetopsites.net/article/53834422.shtml
                        # So ... manually preserve permission bits as given in zinfo
                        if os.name == 'posix':
                            # just set the normal permission bits
                            os.chmod(outfile, (zinfo.external_attr >> 16) & 0x1FF)
                        outfiles.append(outfile)
                        # Double check the digest of the written file
                        if not dry_run and row[1]:
                            with open(outfile, 'rb') as bf:
                                data = bf.read()
                                _, newdigest = self.get_hash(data, kind)
                                if newdigest != digest:
                                    raise DistlibException('digest mismatch '
                                                           'on write for '
                                                           '%s' % outfile)
                        if bc and outfile.endswith('.py'):
                            try:
                                pyc = fileop.byte_compile(outfile, hashed_invalidation=bc_hashed_invalidation)
                                outfiles.append(pyc)
                            except Exception:
                                # Don't give up if byte-compilation fails,
                                # but log it and perhaps warn the user
                                logger.warning('Byte-compilation failed', exc_info=True)
                    else:
                        fn = os.path.basename(convert_path(arcname))
                        workname = os.path.join(workdir, fn)
                        with zf.open(arcname) as bf:
                            fileop.copy_stream(bf, workname)

                        dn, fn = os.path.split(outfile)
                        maker.target_dir = dn
                        filenames = maker.make(fn)
                        fileop.set_executable_mode(filenames)
                        outfiles.extend(filenames)

                if lib_only:
                    logger.debug('lib_only: returning None')
                    dist = None
                else:
                    # Generate scripts

                    # Try to get pydist.json so we can see if there are
                    # any commands to generate. If this fails (e.g. because
                    # of a legacy wheel), log a warning but don't give up.
                    commands = None
                    file_version = self.info['Wheel-Version']
                    if file_version == '1.0':
                        # Use legacy info
                        ep = posixpath.join(info_dir, 'entry_points.txt')
                        try:
                            with zf.open(ep) as bwf:
                                epdata = read_exports(bwf)
                            commands = {}
                            for key in ('console', 'gui'):
                                k = '%s_scripts' % key
                                if k in epdata:
                                    commands['wrap_%s' % key] = d = {}
                                    for v in epdata[k].values():
                                        s = '%s:%s' % (v.prefix, v.suffix)
                                        if v.flags:
                                            s += ' [%s]' % ','.join(v.flags)
                                        d[v.name] = s
                        except Exception:
                            logger.warning('Unable to read legacy script '
                                           'metadata, so cannot generate '
                                           'scripts')
                    else:
                        try:
                            with zf.open(metadata_name) as bwf:
                                wf = wrapper(bwf)
                                commands = json.load(wf).get('extensions')
                                if commands:
                                    commands = commands.get('python.commands')
                        except Exception:
                            logger.warning('Unable to read JSON metadata, so '
                                           'cannot generate scripts')
                    if commands:
                        console_scripts = commands.get('wrap_console', {})
                        gui_scripts = commands.get('wrap_gui', {})
                        if console_scripts or gui_scripts:
                            script_dir = paths.get('scripts', '')
                            if not os.path.isdir(script_dir):
                                raise ValueError('Valid script path not '
                                                 'specified')
                            maker.target_dir = script_dir
                            for k, v in console_scripts.items():
                                script = '%s = %s' % (k, v)
                                filenames = maker.make(script)
                                fileop.set_executable_mode(filenames)

                            if gui_scripts:
                                options = {'gui': True}
                                for k, v in gui_scripts.items():
                                    script = '%s = %s' % (k, v)
                                    filenames = maker.make(script, options)
                                    fileop.set_executable_mode(filenames)

                    p = os.path.join(libdir, info_dir)
                    dist = InstalledDistribution(p)

                    # Write SHARED
                    paths = dict(paths)  # don't change passed in dict
                    del paths['purelib']
                    del paths['platlib']
                    paths['lib'] = libdir
                    p = dist.write_shared_locations(paths, dry_run)
                    if p:
                        outfiles.append(p)

                    # Write RECORD
                    dist.write_installed_files(outfiles, paths['prefix'], dry_run)
                return dist
            except Exception:  # pragma: no cover
                logger.exception('installation failed.')
                fileop.rollback()
                raise
            finally:
                shutil.rmtree(workdir)

    def _get_dylib_cache(self):
        global cache
        if cache is None:
            # Use native string to avoid issues on 2.x: see Python #20140.
            base = os.path.join(get_cache_base(), str('dylib-cache'), '%s.%s' % sys.version_info[:2])
            cache = Cache(base)
        return cache

    def _get_extensions(self):
        pathname = os.path.join(self.dirname, self.filename)
        name_ver = '%s-%s' % (self.name, self.version)
        info_dir = '%s.dist-info' % name_ver
        arcname = posixpath.join(info_dir, 'EXTENSIONS')
        wrapper = codecs.getreader('utf-8')
        result = []
        with ZipFile(pathname, 'r') as zf:
            try:
                with zf.open(arcname) as bf:
                    wf = wrapper(bf)
                    extensions = json.load(wf)
                    cache = self._get_dylib_cache()
                    prefix = cache.prefix_to_dir(self.filename, use_abspath=False)
                    cache_base = os.path.join(cache.base, prefix)
                    if not os.path.isdir(cache_base):
                        os.makedirs(cache_base)
                    for name, relpath in extensions.items():
                        dest = os.path.join(cache_base, convert_path(relpath))
                        if not os.path.exists(dest):
                            extract = True
                        else:
                            file_time = os.stat(dest).st_mtime
                            file_time = datetime.datetime.fromtimestamp(file_time)
                            info = zf.getinfo(relpath)
                            wheel_time = datetime.datetime(*info.date_time)
                            extract = wheel_time > file_time
                        if extract:
                            zf.extract(relpath, cache_base)
                        result.append((name, dest))
            except KeyError:
                pass
        return result

    def is_compatible(self):
        """
        Determine if a wheel is compatible with the running system.
        """
        return is_compatible(self)

    def is_mountable(self):
        """
        Determine if a wheel is asserted as mountable by its metadata.
        """
        return True  # for now - metadata details TBD

    def mount(self, append=False):
        pathname = os.path.abspath(os.path.join(self.dirname, self.filename))
        if not self.is_compatible():
            msg = 'Wheel %s not compatible with this Python.' % pathname
            raise DistlibException(msg)
        if not self.is_mountable():
            msg = 'Wheel %s is marked as not mountable.' % pathname
            raise DistlibException(msg)
        if pathname in sys.path:
            logger.debug('%s already in path', pathname)
        else:
            if append:
                sys.path.append(pathname)
            else:
                sys.path.insert(0, pathname)
            extensions = self._get_extensions()
            if extensions:
                if _hook not in sys.meta_path:
                    sys.meta_path.append(_hook)
                _hook.add(pathname, extensions)

    def unmount(self):
        pathname = os.path.abspath(os.path.join(self.dirname, self.filename))
        if pathname not in sys.path:
            logger.debug('%s not in path', pathname)
        else:
            sys.path.remove(pathname)
            if pathname in _hook.impure_wheels:
                _hook.remove(pathname)
            if not _hook.impure_wheels:
                if _hook in sys.meta_path:
                    sys.meta_path.remove(_hook)

    def verify(self):
        pathname = os.path.join(self.dirname, self.filename)
        name_ver = '%s-%s' % (self.name, self.version)
        # data_dir = '%s.data' % name_ver
        info_dir = '%s.dist-info' % name_ver

        # metadata_name = posixpath.join(info_dir, LEGACY_METADATA_FILENAME)
        wheel_metadata_name = posixpath.join(info_dir, 'WHEEL')
        record_name = posixpath.join(info_dir, 'RECORD')

        wrapper = codecs.getreader('utf-8')

        with ZipFile(pathname, 'r') as zf:
            with zf.open(wheel_metadata_name) as bwf:
                wf = wrapper(bwf)
                message_from_file(wf)
            # wv = message['Wheel-Version'].split('.', 1)
            # file_version = tuple([int(i) for i in wv])
            # TODO version verification

            records = {}
            with zf.open(record_name) as bf:
                with CSVReader(stream=bf) as reader:
                    for row in reader:
                        p = row[0]
                        records[p] = row

            for zinfo in zf.infolist():
                arcname = zinfo.filename
                if isinstance(arcname, text_type):
                    u_arcname = arcname
                else:
                    u_arcname = arcname.decode('utf-8')
                # See issue #115: some wheels have .. in their entries, but
                # in the filename ... e.g. __main__..py ! So the check is
                # updated to look for .. in the directory portions
                p = u_arcname.split('/')
                if '..' in p:
                    raise DistlibException('invalid entry in '
                                           'wheel: %r' % u_arcname)

                if self.skip_entry(u_arcname):
                    continue
                row = records[u_arcname]
                if row[2] and str(zinfo.file_size) != row[2]:
                    raise DistlibException('size mismatch for '
                                           '%s' % u_arcname)
                if row[1]:
                    kind, value = row[1].split('=', 1)
                    with zf.open(arcname) as bf:
                        data = bf.read()
                    _, digest = self.get_hash(data, kind)
                    if digest != value:
                        raise DistlibException('digest mismatch for '
                                               '%s' % arcname)

    def update(self, modifier, dest_dir=None, **kwargs):
        """
        Update the contents of a wheel in a generic way. The modifier should
        be a callable which expects a dictionary argument: its keys are
        archive-entry paths, and its values are absolute filesystem paths
        where the contents the corresponding archive entries can be found. The
        modifier is free to change the contents of the files pointed to, add
        new entries and remove entries, before returning. This method will
        extract the entire contents of the wheel to a temporary location, call
        the modifier, and then use the passed (and possibly updated)
        dictionary to write a new wheel. If ``dest_dir`` is specified, the new
        wheel is written there -- otherwise, the original wheel is overwritten.

        The modifier should return True if it updated the wheel, else False.
        This method returns the same value the modifier returns.
        """

        def get_version(path_map, info_dir):
            version = path = None
            key = '%s/%s' % (info_dir, LEGACY_METADATA_FILENAME)
            if key not in path_map:
                key = '%s/PKG-INFO' % info_dir
            if key in path_map:
                path = path_map[key]
                version = Metadata(path=path).version
            return version, path

        def update_version(version, path):
            updated = None
            try:
                NormalizedVersion(version)
                i = version.find('-')
                if i < 0:
                    updated = '%s+1' % version
                else:
                    parts = [int(s) for s in version[i + 1:].split('.')]
                    parts[-1] += 1
                    updated = '%s+%s' % (version[:i], '.'.join(str(i) for i in parts))
            except UnsupportedVersionError:
                logger.debug('Cannot update non-compliant (PEP-440) '
                             'version %r', version)
            if updated:
                md = Metadata(path=path)
                md.version = updated
                legacy = path.endswith(LEGACY_METADATA_FILENAME)
                md.write(path=path, legacy=legacy)
                logger.debug('Version updated from %r to %r', version, updated)

        pathname = os.path.join(self.dirname, self.filename)
        name_ver = '%s-%s' % (self.name, self.version)
        info_dir = '%s.dist-info' % name_ver
        record_name = posixpath.join(info_dir, 'RECORD')
        with tempdir() as workdir:
            with ZipFile(pathname, 'r') as zf:
                path_map = {}
                for zinfo in zf.infolist():
                    arcname = zinfo.filename
                    if isinstance(arcname, text_type):
                        u_arcname = arcname
                    else:
                        u_arcname = arcname.decode('utf-8')
                    if u_arcname == record_name:
                        continue
                    if '..' in u_arcname:
                        raise DistlibException('invalid entry in '
                                               'wheel: %r' % u_arcname)
                    zf.extract(zinfo, workdir)
                    path = os.path.join(workdir, convert_path(u_arcname))
                    path_map[u_arcname] = path

            # Remember the version.
            original_version, _ = get_version(path_map, info_dir)
            # Files extracted. Call the modifier.
            modified = modifier(path_map, **kwargs)
            if modified:
                # Something changed - need to build a new wheel.
                current_version, path = get_version(path_map, info_dir)
                if current_version and (current_version == original_version):
                    # Add or update local version to signify changes.
                    update_version(current_version, path)
                # Decide where the new wheel goes.
                if dest_dir is None:
                    fd, newpath = tempfile.mkstemp(suffix='.whl', prefix='wheel-update-', dir=workdir)
                    os.close(fd)
                else:
                    if not os.path.isdir(dest_dir):
                        raise DistlibException('Not a directory: %r' % dest_dir)
                    newpath = os.path.join(dest_dir, self.filename)
                archive_paths = list(path_map.items())
                distinfo = os.path.join(workdir, info_dir)
                info = distinfo, info_dir
                self.write_records(info, workdir, archive_paths)
                self.build_zip(newpath, archive_paths)
                if dest_dir is None:
                    shutil.copyfile(newpath, pathname)
        return modified


def _get_glibc_version():
    import platform
    ver = platform.libc_ver()
    result = []
    if ver[0] == 'glibc':
        for s in ver[1].split('.'):
            result.append(int(s) if s.isdigit() else 0)
        result = tuple(result)
    return result


def compatible_tags():
    """
    Return (pyver, abi, arch) tuples compatible with this Python.
    """
    class _Version:
        def __init__(self, major, minor):
            self.major = major
            self.major_minor = (major, minor)
            self.string = ''.join((str(major), str(minor)))

        def __str__(self):
            return self.string


    versions = [
        _Version(sys.version_info.major, minor_version)
        for minor_version in range(sys.version_info.minor, -1, -1)
    ]
    abis = []
    for suffix in _get_suffixes():
        if suffix.startswith('.abi'):
            abis.append(suffix.split('.', 2)[1])
    abis.sort()
    if ABI != 'none':
        abis.insert(0, ABI)
    abis.append('none')
    result = []

    arches = [ARCH]
    if sys.platform == 'darwin':
        m = re.match(r'(\w+)_(\d+)_(\d+)_(\w+)$', ARCH)
        if m:
            name, major, minor, arch = m.groups()
            minor = int(minor)
            matches = [arch]
            if arch in ('i386', 'ppc'):
                matches.append('fat')
            if arch in ('i386', 'ppc', 'x86_64'):
                matches.append('fat3')
            if arch in ('ppc64', 'x86_64'):
                matches.append('fat64')
            if arch in ('i386', 'x86_64'):
                matches.append('intel')
            if arch in ('i386', 'x86_64', 'intel', 'ppc', 'ppc64'):
                matches.append('universal')
            while minor >= 0:
                for match in matches:
                    s = '%s_%s_%s_%s' % (name, major, minor, match)
                    if s != ARCH:  # already there
                        arches.append(s)
                minor -= 1

    # Most specific - our Python version, ABI and arch
    for i, version_object in enumerate(versions):
        version = str(version_object)
        add_abis = []

        if i == 0:
            add_abis = abis

        if IMP_PREFIX == 'cp' and version_object.major_minor >= (3, 2):
            limited_api_abi = 'abi' + str(version_object.major)
            if limited_api_abi not in add_abis:
                add_abis.append(limited_api_abi)

        for abi in add_abis:
            for arch in arches:
                result.append((''.join((IMP_PREFIX, version)), abi, arch))
                # manylinux
                if abi != 'none' and sys.platform.startswith('linux'):
                    arch = arch.replace('linux_', '')
                    parts = _get_glibc_version()
                    if len(parts) == 2:
                        if parts >= (2, 5):
                            result.append((''.join((IMP_PREFIX, version)), abi, 'manylinux1_%s' % arch))
                        if parts >= (2, 12):
                            result.append((''.join((IMP_PREFIX, version)), abi, 'manylinux2010_%s' % arch))
                        if parts >= (2, 17):
                            result.append((''.join((IMP_PREFIX, version)), abi, 'manylinux2014_%s' % arch))
                        result.append((''.join(
                            (IMP_PREFIX, version)), abi, 'manylinux_%s_%s_%s' % (parts[0], parts[1], arch)))

    # where no ABI / arch dependency, but IMP_PREFIX dependency
    for i, version_object in enumerate(versions):
        version = str(version_object)
        result.append((''.join((IMP_PREFIX, version)), 'none', 'any'))
        if i == 0:
            result.append((''.join((IMP_PREFIX, version[0])), 'none', 'any'))

    # no IMP_PREFIX, ABI or arch dependency
    for i, version_object in enumerate(versions):
        version = str(version_object)
        result.append((''.join(('py', version)), 'none', 'any'))
        if i == 0:
            result.append((''.join(('py', version[0])), 'none', 'any'))

    return set(result)


COMPATIBLE_TAGS = compatible_tags()

del compatible_tags


def is_compatible(wheel, tags=None):
    if not isinstance(wheel, Wheel):
        wheel = Wheel(wheel)  # assume it's a filename
    result = False
    if tags is None:
        tags = COMPATIBLE_TAGS
    for ver, abi, arch in tags:
        if ver in wheel.pyver and abi in wheel.abi and arch in wheel.arch:
            result = True
            break
    return result
1,101 lines•42.9 KB
python
.venv/Lib/site-packages/pip/_vendor/rich/live.py
Raw Download
Find: Go to:
import sys
from threading import Event, RLock, Thread
from types import TracebackType
from typing import IO, Any, Callable, List, Optional, TextIO, Type, cast

from . import get_console
from .console import Console, ConsoleRenderable, RenderableType, RenderHook
from .control import Control
from .file_proxy import FileProxy
from .jupyter import JupyterMixin
from .live_render import LiveRender, VerticalOverflowMethod
from .screen import Screen
from .text import Text


class _RefreshThread(Thread):
    """A thread that calls refresh() at regular intervals."""

    def __init__(self, live: "Live", refresh_per_second: float) -> None:
        self.live = live
        self.refresh_per_second = refresh_per_second
        self.done = Event()
        super().__init__(daemon=True)

    def stop(self) -> None:
        self.done.set()

    def run(self) -> None:
        while not self.done.wait(1 / self.refresh_per_second):
            with self.live._lock:
                if not self.done.is_set():
                    self.live.refresh()


class Live(JupyterMixin, RenderHook):
    """Renders an auto-updating live display of any given renderable.

    Args:
        renderable (RenderableType, optional): The renderable to live display. Defaults to displaying nothing.
        console (Console, optional): Optional Console instance. Default will an internal Console instance writing to stdout.
        screen (bool, optional): Enable alternate screen mode. Defaults to False.
        auto_refresh (bool, optional): Enable auto refresh. If disabled, you will need to call `refresh()` or `update()` with refresh flag. Defaults to True
        refresh_per_second (float, optional): Number of times per second to refresh the live display. Defaults to 4.
        transient (bool, optional): Clear the renderable on exit (has no effect when screen=True). Defaults to False.
        redirect_stdout (bool, optional): Enable redirection of stdout, so ``print`` may be used. Defaults to True.
        redirect_stderr (bool, optional): Enable redirection of stderr. Defaults to True.
        vertical_overflow (VerticalOverflowMethod, optional): How to handle renderable when it is too tall for the console. Defaults to "ellipsis".
        get_renderable (Callable[[], RenderableType], optional): Optional callable to get renderable. Defaults to None.
    """

    def __init__(
        self,
        renderable: Optional[RenderableType] = None,
        *,
        console: Optional[Console] = None,
        screen: bool = False,
        auto_refresh: bool = True,
        refresh_per_second: float = 4,
        transient: bool = False,
        redirect_stdout: bool = True,
        redirect_stderr: bool = True,
        vertical_overflow: VerticalOverflowMethod = "ellipsis",
        get_renderable: Optional[Callable[[], RenderableType]] = None,
    ) -> None:
        assert refresh_per_second > 0, "refresh_per_second must be > 0"
        self._renderable = renderable
        self.console = console if console is not None else get_console()
        self._screen = screen
        self._alt_screen = False

        self._redirect_stdout = redirect_stdout
        self._redirect_stderr = redirect_stderr
        self._restore_stdout: Optional[IO[str]] = None
        self._restore_stderr: Optional[IO[str]] = None

        self._lock = RLock()
        self.ipy_widget: Optional[Any] = None
        self.auto_refresh = auto_refresh
        self._started: bool = False
        self.transient = True if screen else transient

        self._refresh_thread: Optional[_RefreshThread] = None
        self.refresh_per_second = refresh_per_second

        self.vertical_overflow = vertical_overflow
        self._get_renderable = get_renderable
        self._live_render = LiveRender(
            self.get_renderable(), vertical_overflow=vertical_overflow
        )

    @property
    def is_started(self) -> bool:
        """Check if live display has been started."""
        return self._started

    def get_renderable(self) -> RenderableType:
        renderable = (
            self._get_renderable()
            if self._get_renderable is not None
            else self._renderable
        )
        return renderable or ""

    def start(self, refresh: bool = False) -> None:
        """Start live rendering display.

        Args:
            refresh (bool, optional): Also refresh. Defaults to False.
        """
        with self._lock:
            if self._started:
                return
            self.console.set_live(self)
            self._started = True
            if self._screen:
                self._alt_screen = self.console.set_alt_screen(True)
            self.console.show_cursor(False)
            self._enable_redirect_io()
            self.console.push_render_hook(self)
            if refresh:
                try:
                    self.refresh()
                except Exception:
                    # If refresh fails, we want to stop the redirection of sys.stderr,
                    # so the error stacktrace is properly displayed in the terminal.
                    # (or, if the code that calls Rich captures the exception and wants to display something,
                    # let this be displayed in the terminal).
                    self.stop()
                    raise
            if self.auto_refresh:
                self._refresh_thread = _RefreshThread(self, self.refresh_per_second)
                self._refresh_thread.start()

    def stop(self) -> None:
        """Stop live rendering display."""
        with self._lock:
            if not self._started:
                return
            self.console.clear_live()
            self._started = False

            if self.auto_refresh and self._refresh_thread is not None:
                self._refresh_thread.stop()
                self._refresh_thread = None
            # allow it to fully render on the last even if overflow
            self.vertical_overflow = "visible"
            with self.console:
                try:
                    if not self._alt_screen and not self.console.is_jupyter:
                        self.refresh()
                finally:
                    self._disable_redirect_io()
                    self.console.pop_render_hook()
                    if not self._alt_screen and self.console.is_terminal:
                        self.console.line()
                    self.console.show_cursor(True)
                    if self._alt_screen:
                        self.console.set_alt_screen(False)

                    if self.transient and not self._alt_screen:
                        self.console.control(self._live_render.restore_cursor())
                    if self.ipy_widget is not None and self.transient:
                        self.ipy_widget.close()  # pragma: no cover

    def __enter__(self) -> "Live":
        self.start(refresh=self._renderable is not None)
        return self

    def __exit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc_val: Optional[BaseException],
        exc_tb: Optional[TracebackType],
    ) -> None:
        self.stop()

    def _enable_redirect_io(self) -> None:
        """Enable redirecting of stdout / stderr."""
        if self.console.is_terminal or self.console.is_jupyter:
            if self._redirect_stdout and not isinstance(sys.stdout, FileProxy):
                self._restore_stdout = sys.stdout
                sys.stdout = cast("TextIO", FileProxy(self.console, sys.stdout))
            if self._redirect_stderr and not isinstance(sys.stderr, FileProxy):
                self._restore_stderr = sys.stderr
                sys.stderr = cast("TextIO", FileProxy(self.console, sys.stderr))

    def _disable_redirect_io(self) -> None:
        """Disable redirecting of stdout / stderr."""
        if self._restore_stdout:
            sys.stdout = cast("TextIO", self._restore_stdout)
            self._restore_stdout = None
        if self._restore_stderr:
            sys.stderr = cast("TextIO", self._restore_stderr)
            self._restore_stderr = None

    @property
    def renderable(self) -> RenderableType:
        """Get the renderable that is being displayed

        Returns:
            RenderableType: Displayed renderable.
        """
        renderable = self.get_renderable()
        return Screen(renderable) if self._alt_screen else renderable

    def update(self, renderable: RenderableType, *, refresh: bool = False) -> None:
        """Update the renderable that is being displayed

        Args:
            renderable (RenderableType): New renderable to use.
            refresh (bool, optional): Refresh the display. Defaults to False.
        """
        if isinstance(renderable, str):
            renderable = self.console.render_str(renderable)
        with self._lock:
            self._renderable = renderable
            if refresh:
                self.refresh()

    def refresh(self) -> None:
        """Update the display of the Live Render."""
        with self._lock:
            self._live_render.set_renderable(self.renderable)
            if self.console.is_jupyter:  # pragma: no cover
                try:
                    from IPython.display import display
                    from ipywidgets import Output
                except ImportError:
                    import warnings

                    warnings.warn('install "ipywidgets" for Jupyter support')
                else:
                    if self.ipy_widget is None:
                        self.ipy_widget = Output()
                        display(self.ipy_widget)

                    with self.ipy_widget:
                        self.ipy_widget.clear_output(wait=True)
                        self.console.print(self._live_render.renderable)
            elif self.console.is_terminal and not self.console.is_dumb_terminal:
                with self.console:
                    self.console.print(Control())
            elif (
                not self._started and not self.transient
            ):  # if it is finished allow files or dumb-terminals to see final result
                with self.console:
                    self.console.print(Control())

    def process_renderables(
        self, renderables: List[ConsoleRenderable]
    ) -> List[ConsoleRenderable]:
        """Process renderables to restore cursor and display progress."""
        self._live_render.vertical_overflow = self.vertical_overflow
        if self.console.is_interactive:
            # lock needs acquiring as user can modify live_render renderable at any time unlike in Progress.
            with self._lock:
                reset = (
                    Control.home()
                    if self._alt_screen
                    else self._live_render.position_cursor()
                )
                renderables = [reset, *renderables, self._live_render]
        elif (
            not self._started and not self.transient
        ):  # if it is finished render the final output for files or dumb_terminals
            renderables = [*renderables, self._live_render]

        return renderables


if __name__ == "__main__":  # pragma: no cover
    import random
    import time
    from itertools import cycle
    from typing import Dict, List, Tuple

    from .align import Align
    from .console import Console
    from .live import Live as Live
    from .panel import Panel
    from .rule import Rule
    from .syntax import Syntax
    from .table import Table

    console = Console()

    syntax = Syntax(
        '''def loop_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]:
    """Iterate and generate a tuple with a flag for last value."""
    iter_values = iter(values)
    try:
        previous_value = next(iter_values)
    except StopIteration:
        return
    for value in iter_values:
        yield False, previous_value
        previous_value = value
    yield True, previous_value''',
        "python",
        line_numbers=True,
    )

    table = Table("foo", "bar", "baz")
    table.add_row("1", "2", "3")

    progress_renderables = [
        "You can make the terminal shorter and taller to see the live table hide"
        "Text may be printed while the progress bars are rendering.",
        Panel("In fact, [i]any[/i] renderable will work"),
        "Such as [magenta]tables[/]...",
        table,
        "Pretty printed structures...",
        {"type": "example", "text": "Pretty printed"},
        "Syntax...",
        syntax,
        Rule("Give it a try!"),
    ]

    examples = cycle(progress_renderables)

    exchanges = [
        "SGD",
        "MYR",
        "EUR",
        "USD",
        "AUD",
        "JPY",
        "CNH",
        "HKD",
        "CAD",
        "INR",
        "DKK",
        "GBP",
        "RUB",
        "NZD",
        "MXN",
        "IDR",
        "TWD",
        "THB",
        "VND",
    ]
    with Live(console=console) as live_table:
        exchange_rate_dict: Dict[Tuple[str, str], float] = {}

        for index in range(100):
            select_exchange = exchanges[index % len(exchanges)]

            for exchange in exchanges:
                if exchange == select_exchange:
                    continue
                time.sleep(0.4)
                if random.randint(0, 10) < 1:
                    console.log(next(examples))
                exchange_rate_dict[(select_exchange, exchange)] = 200 / (
                    (random.random() * 320) + 1
                )
                if len(exchange_rate_dict) > len(exchanges) - 1:
                    exchange_rate_dict.pop(list(exchange_rate_dict.keys())[0])
                table = Table(title="Exchange Rates")

                table.add_column("Source Currency")
                table.add_column("Destination Currency")
                table.add_column("Exchange Rate")

                for (source, dest), exchange_rate in exchange_rate_dict.items():
                    table.add_row(
                        source,
                        dest,
                        Text(
                            f"{exchange_rate:.4f}",
                            style="red" if exchange_rate < 1.0 else "green",
                        ),
                    )

                live_table.update(Align.center(table))
376 lines•13.9 KB
python
.venv/Lib/site-packages/pip/_vendor/rich/_wrap.py
Raw Download
Find: Go to:
from __future__ import annotations

import re
from typing import Iterable

from ._loop import loop_last
from .cells import cell_len, chop_cells

re_word = re.compile(r"\s*\S+\s*")


def words(text: str) -> Iterable[tuple[int, int, str]]:
    """Yields each word from the text as a tuple
    containing (start_index, end_index, word). A "word" in this context may
    include the actual word and any whitespace to the right.
    """
    position = 0
    word_match = re_word.match(text, position)
    while word_match is not None:
        start, end = word_match.span()
        word = word_match.group(0)
        yield start, end, word
        word_match = re_word.match(text, end)


def divide_line(text: str, width: int, fold: bool = True) -> list[int]:
    """Given a string of text, and a width (measured in cells), return a list
    of cell offsets which the string should be split at in order for it to fit
    within the given width.

    Args:
        text: The text to examine.
        width: The available cell width.
        fold: If True, words longer than `width` will be folded onto a new line.

    Returns:
        A list of indices to break the line at.
    """
    break_positions: list[int] = []  # offsets to insert the breaks at
    append = break_positions.append
    cell_offset = 0
    _cell_len = cell_len

    for start, _end, word in words(text):
        word_length = _cell_len(word.rstrip())
        remaining_space = width - cell_offset
        word_fits_remaining_space = remaining_space >= word_length

        if word_fits_remaining_space:
            # Simplest case - the word fits within the remaining width for this line.
            cell_offset += _cell_len(word)
        else:
            # Not enough space remaining for this word on the current line.
            if word_length > width:
                # The word doesn't fit on any line, so we can't simply
                # place it on the next line...
                if fold:
                    # Fold the word across multiple lines.
                    folded_word = chop_cells(word, width=width)
                    for last, line in loop_last(folded_word):
                        if start:
                            append(start)
                        if last:
                            cell_offset = _cell_len(line)
                        else:
                            start += len(line)
                else:
                    # Folding isn't allowed, so crop the word.
                    if start:
                        append(start)
                    cell_offset = _cell_len(word)
            elif cell_offset and start:
                # The word doesn't fit within the remaining space on the current
                # line, but it *can* fit on to the next (empty) line.
                append(start)
                cell_offset = _cell_len(word)

    return break_positions


if __name__ == "__main__":  # pragma: no cover
    from .console import Console

    console = Console(width=10)
    console.print("12345 abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ 12345")
    print(chop_cells("abcdefghijklmnopqrstuvwxyz", 10))

    console = Console(width=20)
    console.rule()
    console.print("TextualはPythonの高速アプリケーション開発フレームワークです")

    console.rule()
    console.print("アプリケーションは1670万色を使用でき")
94 lines•3.3 KB
python
.venv/Lib/site-packages/pip/_vendor/resolvelib/structs.py
Raw Download
Find: Go to:
import itertools

from .compat import collections_abc


class DirectedGraph(object):
    """A graph structure with directed edges."""

    def __init__(self):
        self._vertices = set()
        self._forwards = {}  # <key> -> Set[<key>]
        self._backwards = {}  # <key> -> Set[<key>]

    def __iter__(self):
        return iter(self._vertices)

    def __len__(self):
        return len(self._vertices)

    def __contains__(self, key):
        return key in self._vertices

    def copy(self):
        """Return a shallow copy of this graph."""
        other = DirectedGraph()
        other._vertices = set(self._vertices)
        other._forwards = {k: set(v) for k, v in self._forwards.items()}
        other._backwards = {k: set(v) for k, v in self._backwards.items()}
        return other

    def add(self, key):
        """Add a new vertex to the graph."""
        if key in self._vertices:
            raise ValueError("vertex exists")
        self._vertices.add(key)
        self._forwards[key] = set()
        self._backwards[key] = set()

    def remove(self, key):
        """Remove a vertex from the graph, disconnecting all edges from/to it."""
        self._vertices.remove(key)
        for f in self._forwards.pop(key):
            self._backwards[f].remove(key)
        for t in self._backwards.pop(key):
            self._forwards[t].remove(key)

    def connected(self, f, t):
        return f in self._backwards[t] and t in self._forwards[f]

    def connect(self, f, t):
        """Connect two existing vertices.

        Nothing happens if the vertices are already connected.
        """
        if t not in self._vertices:
            raise KeyError(t)
        self._forwards[f].add(t)
        self._backwards[t].add(f)

    def iter_edges(self):
        for f, children in self._forwards.items():
            for t in children:
                yield f, t

    def iter_children(self, key):
        return iter(self._forwards[key])

    def iter_parents(self, key):
        return iter(self._backwards[key])


class IteratorMapping(collections_abc.Mapping):
    def __init__(self, mapping, accessor, appends=None):
        self._mapping = mapping
        self._accessor = accessor
        self._appends = appends or {}

    def __repr__(self):
        return "IteratorMapping({!r}, {!r}, {!r})".format(
            self._mapping,
            self._accessor,
            self._appends,
        )

    def __bool__(self):
        return bool(self._mapping or self._appends)

    __nonzero__ = __bool__  # XXX: Python 2.

    def __contains__(self, key):
        return key in self._mapping or key in self._appends

    def __getitem__(self, k):
        try:
            v = self._mapping[k]
        except KeyError:
            return iter(self._appends[k])
        return itertools.chain(self._accessor(v), self._appends.get(k, ()))

    def __iter__(self):
        more = (k for k in self._appends if k not in self._mapping)
        return itertools.chain(self._mapping, more)

    def __len__(self):
        more = sum(1 for k in self._appends if k not in self._mapping)
        return len(self._mapping) + more


class _FactoryIterableView(object):
    """Wrap an iterator factory returned by `find_matches()`.

    Calling `iter()` on this class would invoke the underlying iterator
    factory, making it a "collection with ordering" that can be iterated
    through multiple times, but lacks random access methods presented in
    built-in Python sequence types.
    """

    def __init__(self, factory):
        self._factory = factory
        self._iterable = None

    def __repr__(self):
        return "{}({})".format(type(self).__name__, list(self))

    def __bool__(self):
        try:
            next(iter(self))
        except StopIteration:
            return False
        return True

    __nonzero__ = __bool__  # XXX: Python 2.

    def __iter__(self):
        iterable = (
            self._factory() if self._iterable is None else self._iterable
        )
        self._iterable, current = itertools.tee(iterable)
        return current


class _SequenceIterableView(object):
    """Wrap an iterable returned by find_matches().

    This is essentially just a proxy to the underlying sequence that provides
    the same interface as `_FactoryIterableView`.
    """

    def __init__(self, sequence):
        self._sequence = sequence

    def __repr__(self):
        return "{}({})".format(type(self).__name__, self._sequence)

    def __bool__(self):
        return bool(self._sequence)

    __nonzero__ = __bool__  # XXX: Python 2.

    def __iter__(self):
        return iter(self._sequence)


def build_iter_view(matches):
    """Build an iterable view from the value returned by `find_matches()`."""
    if callable(matches):
        return _FactoryIterableView(matches)
    if not isinstance(matches, collections_abc.Sequence):
        matches = list(matches)
    return _SequenceIterableView(matches)
171 lines•4.8 KB
python
🚀 Support RSK World

Subscribe to our YouTube channel for latest tutorials & updates!



Click subscribe & support our work ❤️

About RSK World

Founded by Molla Samser, with Designer & Tester Rima Khatun, RSK World is your one-stop destination for free programming resources, source code, and development tools.

Founder: Molla Samser
Designer & Tester: Rima Khatun

Development

  • Game Development
  • Web Development
  • Mobile Development
  • AI Development
  • Development Tools

Legal

  • Terms & Conditions
  • Privacy Policy
  • Disclaimer

Contact Info

Nutanhat, Mongolkote
Purba Burdwan, West Bengal
India, 713147

+91 93305 39277

hello@rskworld.in
support@rskworld.in

© 2026 RSK World. All rights reserved.

Content used for educational purposes only. View Disclaimer