Bump fpdf2 to 2.8.1 (#12753)

Closes: #12738
This commit is contained in:
Sebastian Rittau
2024-10-10 16:49:39 +02:00
committed by GitHub
parent c490871c32
commit 4f94a0e140
14 changed files with 346 additions and 87 deletions

View File

@@ -8,7 +8,5 @@ fpdf._fonttools_shims
# Only present if harfbuzz is installed
fpdf.fonts.HarfBuzzFont
# Checking the following function crashes stubtest 0.991, but seems to be
# fixed in later versions.
fpdf.FPDF.set_encryption
fpdf.fpdf.FPDF.set_encryption
# Stubtest wants us to use Literals, but that is unreasonable.
fpdf.unicode_script.UNICODE_RANGE_TO_SCRIPT

View File

@@ -1,4 +1,4 @@
version = "2.7.9"
version = "2.8.1"
upstream_repository = "https://github.com/PyFPDF/fpdf2"
requires = ["Pillow>=10.3.0"]

View File

@@ -1,7 +1,7 @@
from pathlib import Path
from .enums import Align as Align, TextMode as TextMode, XPos as XPos, YPos as YPos
from .fonts import FontFace as FontFace
from .fonts import FontFace as FontFace, TextStyle as TextStyle
from .fpdf import FPDF as FPDF, FPDFException as FPDFException, TitleStyle as TitleStyle
from .html import HTML2FPDF as HTML2FPDF, HTMLMixin as HTMLMixin
from .prefs import ViewerPreferences as ViewerPreferences
@@ -25,6 +25,7 @@ __all__ = [
"Template",
"FlexTemplate",
"TitleStyle",
"TextStyle",
"ViewerPreferences",
"HTMLMixin",
"HTML2FPDF",

View File

@@ -75,9 +75,13 @@ class DeviceCMYK(_DeviceCMYKBase):
def rgb8(r, g, b, a: Incomplete | None = None) -> DeviceRGB: ...
def gray8(g, a: Incomplete | None = None) -> DeviceGray: ...
@overload
def convert_to_device_color(r: DeviceGray, g: int = -1, b: int = -1) -> DeviceGray: ...
def convert_to_device_color(r: DeviceCMYK) -> DeviceCMYK: ...
@overload
def convert_to_device_color(r: DeviceRGB, g: int = -1, b: int = -1) -> DeviceRGB: ...
def convert_to_device_color(r: DeviceGray) -> DeviceGray: ...
@overload
def convert_to_device_color(r: DeviceRGB) -> DeviceRGB: ...
@overload
def convert_to_device_color(r: str) -> DeviceRGB: ...
@overload
def convert_to_device_color(r: int, g: Literal[-1] = -1, b: Literal[-1] = -1) -> DeviceGray: ...
@overload

View File

@@ -1,6 +1,6 @@
from enum import Enum, Flag, IntEnum, IntFlag
from typing import Literal
from typing_extensions import Self
from typing_extensions import Self, TypeAlias
from .syntax import Name
@@ -38,6 +38,8 @@ class Align(CoerciveEnum):
R = "RIGHT"
J = "JUSTIFY"
_Align: TypeAlias = Align | Literal["CENTER", "X_CENTER", "LEFT", "RIGHT", "JUSTIFY"] # noqa: Y047
class VAlign(CoerciveEnum):
M = "MIDDLE"
T = "TOP"
@@ -51,6 +53,8 @@ class TextEmphasis(CoerciveIntFlag):
@property
def style(self) -> str: ...
def add(self, value: TextEmphasis) -> TextEmphasis: ...
def remove(self, value: TextEmphasis) -> TextEmphasis: ...
class MethodReturnValue(CoerciveIntFlag):
PAGE_BREAK = 1

View File

@@ -2,8 +2,8 @@ import dataclasses
from _typeshed import Incomplete
from collections.abc import Generator
from dataclasses import dataclass
from typing import overload
from typing_extensions import Self
from typing import Final, overload
from typing_extensions import Self, deprecated
from .drawing import DeviceGray, DeviceRGB, Number
from .enums import TextEmphasis
@@ -39,6 +39,40 @@ class FontFace:
@staticmethod
def combine(default_style: FontFace | None, override_style: FontFace | None) -> FontFace: ...
class TextStyle(FontFace):
t_margin: int
l_margin: int
b_margin: int
def __init__(
self,
font_family: str | None = None,
font_style: str | None = None,
font_size_pt: int | None = None,
color: int | tuple[int, int, int] | None = None,
fill_color: int | tuple[int, int, int] | None = None,
underline: bool = False,
t_margin: int | None = None,
l_margin: int | None = None,
b_margin: int | None = None,
): ...
def replace( # type: ignore[override]
self,
/,
font_family: str | None = None,
emphasis: TextEmphasis | None = None,
font_size_pt: int | None = None,
color: int | tuple[int, int, int] | None = None,
fill_color: int | tuple[int, int, int] | None = None,
t_margin: int | None = None,
l_margin: int | None = None,
b_margin: int | None = None,
) -> TextStyle: ...
@deprecated("fpdf.TitleStyle is deprecated since 2.7.10. It has been replaced by fpdf.TextStyle.")
class TitleStyle(TextStyle): ...
__pdoc__: Final[dict[str, bool]]
class _FontMixin:
i: int
type: str

View File

@@ -14,28 +14,33 @@ from PIL import Image
from .annotations import AnnotationDict, PDFEmbeddedFile
from .drawing import DeviceGray, DeviceRGB, DrawingContext, PaintedPath
from .enums import (
AccessPermission,
Align,
AnnotationFlag,
AnnotationName,
Corner,
EncryptionMethod,
FileAttachmentAnnotationName,
MethodReturnValue,
PageLayout,
PageMode,
PathPaintRule,
RenderStyle,
TableBordersLayout,
TableCellFillMode,
TableHeadingsDisplay,
TextDirection,
TextEmphasis,
TextMarkupType,
TextMode as TextMode,
VAlign,
WrapMode as WrapMode,
XPos as XPos,
YPos as YPos,
_Align,
)
from .errors import FPDFException as FPDFException
from .fonts import FontFace
from .fonts import FontFace, TextStyle, TitleStyle as TitleStyle
from .graphics_state import GraphicsStateMixin
from .html import HTML2FPDF
from .image_datastructures import (
@@ -73,23 +78,6 @@ _FontStyles: TypeAlias = Literal["", "B", "I", "U", "BU", "UB", "BI", "IB", "IU"
FPDF_VERSION: Final[str]
PAGE_FORMATS: dict[_Format, tuple[float, float]]
class TitleStyle(FontFace):
t_margin: int | None
l_margin: int | None
b_margin: int | None
def __init__(
self,
font_family: str | None = None,
font_style: str | None = None,
font_size_pt: int | None = None,
color: int | tuple[int, int, int] | None = None,
underline: bool = False,
t_margin: int | None = None,
l_margin: int | None = None,
b_margin: int | None = None,
) -> None: ...
class ToCPlaceholder(NamedTuple):
render_function: Callable[[FPDF, Any], object]
start_page: int
@@ -105,6 +93,7 @@ class FPDF(GraphicsStateMixin):
MARKDOWN_BOLD_MARKER: ClassVar[str]
MARKDOWN_ITALICS_MARKER: ClassVar[str]
MARKDOWN_UNDERLINE_MARKER: ClassVar[str]
MARKDOWN_ESCAPE_CHARACTER: ClassVar[str]
MARKDOWN_LINK_REGEX: ClassVar[Pattern[str]]
MARKDOWN_LINK_COLOR: ClassVar[Incomplete | None]
MARKDOWN_LINK_UNDERLINE: ClassVar[bool]
@@ -114,9 +103,11 @@ class FPDF(GraphicsStateMixin):
page: int
pages: dict[int, PDFPage]
fonts: dict[str, _Font]
fonts_used_per_page_number: dict[int, set[int]]
links: dict[int, DestinationXYZ]
embedded_files: list[PDFEmbeddedFile]
image_cache: ImageCache
images_used_per_page_number: dict[int, set[int]]
in_footer: bool
str_alias_nb_pages: str
@@ -128,7 +119,7 @@ class FPDF(GraphicsStateMixin):
oversized_images: Incomplete | None
oversized_images_ratio: float
struct_builder: StructureTreeBuilder
section_title_styles: dict[int, Incomplete]
section_title_styles: dict[int, TextStyle]
core_fonts: dict[str, str]
core_fonts_encoding: str
@@ -149,6 +140,7 @@ class FPDF(GraphicsStateMixin):
compress: bool
pdf_version: str
creation_date: datetime.datetime
graphics_style_names_per_page_number: dict[int, set[str]]
buffer: bytearray | None
@@ -166,21 +158,22 @@ class FPDF(GraphicsStateMixin):
format: _Format | tuple[float, float] = "A4",
font_cache_dir: Literal["DEPRECATED"] = "DEPRECATED",
) -> None: ...
# The following definition crashes stubtest 1.1.1.
# def set_encryption(
# self,
# owner_password: str,
# user_password: str | None = None,
# encryption_method: EncryptionMethod | str = ...,
# permissions: AccessPermission = ...,
# encrypt_metadata: bool = False,
# ) -> None: ...
def set_encryption(
self,
owner_password: str,
user_password: str | None = None,
encryption_method: EncryptionMethod | str = ...,
permissions: AccessPermission = ...,
encrypt_metadata: bool = False,
) -> None: ...
# args and kwargs are passed to HTML2FPDF_CLASS constructor.
def write_html(self, text: str, *args: Any, **kwargs: Any) -> None: ...
@property
def emphasis(self) -> TextEmphasis: ...
@property
def is_ttf_font(self) -> bool: ...
@property
def page_mode(self): ...
def page_mode(self) -> PageMode: ...
@property
def epw(self) -> float: ...
@property
@@ -280,7 +273,7 @@ class FPDF(GraphicsStateMixin):
corner_radius: float = 0,
) -> None: ...
def ellipse(self, x: float, y: float, w: float, h: float, style: RenderStyle | str | None = None) -> None: ...
def circle(self, x: float, y: float, r, style: RenderStyle | str | None = None) -> None: ...
def circle(self, x: float, y: float, radius: float, style: RenderStyle | str | None = None) -> None: ...
def regular_polygon(
self,
x: float,
@@ -326,6 +319,12 @@ class FPDF(GraphicsStateMixin):
clockwise: bool = False,
style: RenderStyle | str | None = None,
) -> None: ...
def bezier(
self,
point_list: Sequence[tuple[int, int]],
closed: bool = False,
style: RenderStyle | Literal["D", "F", "DF", "FD"] | None = None,
) -> None: ...
def add_font(
self,
family: str | None = None,
@@ -429,15 +428,45 @@ class FPDF(GraphicsStateMixin):
def mirror(self, origin, angle) -> Generator[None]: ...
def local_context(
self,
*,
font_family: Incomplete | None = None,
font_style: Incomplete | None = None,
font_size: Incomplete | None = None,
font_size_pt: Incomplete | None = None,
line_width: Incomplete | None = None,
draw_color: Incomplete | None = None,
fill_color: Incomplete | None = None,
text_color: Incomplete | None = None,
dash_pattern: Incomplete | None = None,
**kwargs,
font_size=..., # semi-deprecated, prefer font_size_pt
char_vpos=...,
char_spacing=...,
current_font=...,
denom_lift=...,
denom_scale=...,
font_stretching=...,
nom_lift=...,
nom_scale=...,
sub_lift=...,
sub_scale=...,
sup_lift=...,
sup_scale=...,
text_mode=...,
text_shaping=...,
underline=...,
paint_rule=...,
allow_transparency=...,
auto_close=...,
intersection_rule=...,
fill_opacity=...,
stroke_color=...,
stroke_opacity=...,
blend_mode=...,
stroke_width=...,
stroke_cap_style=...,
stroke_join_style=...,
stroke_miter_limit=...,
stroke_dash_pattern=...,
stroke_dash_phase=...,
) -> _GeneratorContextManager[None]: ...
@property
def accept_page_break(self) -> bool: ...
@@ -513,6 +542,7 @@ class FPDF(GraphicsStateMixin):
dims: tuple[float, float] | None = None,
keep_aspect_ratio: bool = False,
) -> RasterImageInfo | VectorImageInfo: ...
def x_by_align(self, x: _Align, w: int, h: int, img_info: ImageInfo, keep_aspect_ratio: bool) -> int: ...
@deprecated("Deprecated since 2.7.7; use fpdf.image_parsing.preload_image() instead")
def preload_image(
self, name: str | Image.Image | BytesIO, dims: tuple[float, float] | None = None
@@ -558,13 +588,13 @@ class FPDF(GraphicsStateMixin):
def insert_toc_placeholder(self, render_toc_function, pages: int = 1) -> None: ...
def set_section_title_styles(
self,
level0: TitleStyle,
level1: TitleStyle | None = None,
level2: TitleStyle | None = None,
level3: TitleStyle | None = None,
level4: TitleStyle | None = None,
level5: TitleStyle | None = None,
level6: TitleStyle | None = None,
level0: TextStyle,
level1: TextStyle | None = None,
level2: TextStyle | None = None,
level3: TextStyle | None = None,
level4: TextStyle | None = None,
level5: TextStyle | None = None,
level6: TextStyle | None = None,
) -> None: ...
def start_section(self, name: str, level: int = 0, strict: bool = True) -> None: ...
def use_font_face(self, font_face: FontFace) -> _GeneratorContextManager[None]: ...

View File

@@ -1,12 +1,13 @@
from _typeshed import Incomplete, SupportsItemAccess, SupportsKeysAndGetItem, Unused
from _typeshed import Incomplete, SupportsKeysAndGetItem
from collections.abc import Callable, Iterable, Mapping
from html.parser import HTMLParser
from logging import Logger
from typing import ClassVar, Final, Literal, TypedDict, type_check_only
from typing import ClassVar, Final, Literal
from typing_extensions import TypeAlias
from fpdf import FPDF
from .enums import TextEmphasis
from .fonts import FontFace
from .table import Row, Table
@@ -20,17 +21,13 @@ BULLET_WIN1252: Final[str]
DEGREE_WIN1252: Final[str]
HEADING_TAGS: Final[tuple[str, ...]]
DEFAULT_TAG_STYLES: Final[dict[str, FontFace]]
DEFAULT_TAG_INDENTS: Final[dict[str, int]]
INLINE_TAGS: Final[tuple[str, ...]]
BLOCK_TAGS: Final[tuple[str, ...]]
COLOR_DICT: Final[dict[str, str]]
def color_as_decimal(color: str | None = "#000000") -> tuple[int, int, int] | None: ...
def parse_style(elem_attrs: SupportsItemAccess[str, str]) -> None: ...
@type_check_only
class _Emphasis(TypedDict):
b: bool
i: bool
u: bool
def parse_css_style(style_attr: str) -> dict[str, str]: ...
class HTML2FPDF(HTMLParser):
HTML_UNCLOSED_TAGS: ClassVar[tuple[str, ...]]
@@ -41,20 +38,23 @@ class HTML2FPDF(HTMLParser):
ul_bullet_char: str
li_prefix_color: tuple[int, int, int]
warn_on_tags_not_matching: bool
emphasis: _Emphasis
font_size: float
font_family: str
font_size_pt: float
font_emphasis: TextEmphasis
font_color: tuple[int, int, int]
style_stack: list[FontFace]
h: float
follows_trailing_space: bool
follows_heading: bool
href: str
align: str
style_stack: list[FontFace]
indent: int
line_height_stack: list[Incomplete]
ol_type: list[_OLType]
bullet: list[Incomplete]
font_color: tuple[int, int, int]
heading_level: Incomplete | None
heading_above: float
heading_below: float
table_line_separators: bool
table: Table | None
table_row: Row | None
@@ -63,32 +63,25 @@ class HTML2FPDF(HTMLParser):
tag_indents: dict[str, int]
tag_styles: dict[str, FontFace]
# Not initialized in __init__:
font_family: str
h: float
def __init__(
self,
pdf: FPDF,
image_map: Callable[[str], str] | None = None,
li_tag_indent: int = 5,
dd_tag_indent: int = 10,
li_tag_indent: int | None = None,
dd_tag_indent: int | None = None,
table_line_separators: bool = False,
ul_bullet_char: str = "\x95",
li_prefix_color: tuple[int, int, int] = (190, 0, 0),
heading_sizes: SupportsKeysAndGetItem[str, int] | Iterable[tuple[str, int]] | None = None,
pre_code_font: str = ...,
pre_code_font: str | None = None,
warn_on_tags_not_matching: bool = True,
tag_indents: dict[str, int] | None = None,
tag_styles: Mapping[str, FontFace] | None = None,
**_: Unused,
): ...
font_family: str = "times",
) -> None: ...
def handle_data(self, data) -> None: ...
def handle_starttag(self, tag, attrs) -> None: ...
def handle_endtag(self, tag) -> None: ...
def set_font(self, family: str | None = None, size: float | None = None, set_default: bool = False) -> None: ...
def set_style(self, tag: Incomplete | None = None, enable: bool = False) -> None: ...
def set_text_color(self, r: Incomplete | None = None, g: int = 0, b: int = 0) -> None: ...
def put_link(self, text) -> None: ...
def render_toc(self, pdf, outline) -> None: ...
def error(self, message: str) -> None: ...

View File

@@ -4,7 +4,6 @@ from typing import Any, Literal
from typing_extensions import TypeAlias
from fpdf.enums import Align
from fpdf.fpdf import FPDF
from .image_parsing import _ImageFilter
@@ -31,7 +30,7 @@ _AlignLiteral: TypeAlias = Literal[
"r",
"j",
]
_TextAlign: TypeAlias = Align | _AlignLiteral
_TextAlign: TypeAlias = Align | _AlignLiteral # noqa: Y047
class ImageInfo(dict[str, Any]):
@property
@@ -43,8 +42,6 @@ class ImageInfo(dict[str, Any]):
@property
def rendered_height(self) -> int: ...
def scale_inside_box(self, x: float, y: float, w: float, h: float) -> tuple[float, float, float, float]: ...
@staticmethod
def x_by_align(x: _TextAlign, w: float, pdf: FPDF, keep_aspect_ratio: Literal[False]) -> float: ...
class RasterImageInfo(ImageInfo):
def size_in_document_units(self, w: float, h: float, scale=1) -> tuple[float, float]: ...

View File

@@ -7,6 +7,8 @@ from .enums import Align, TextDirection, WrapMode
SOFT_HYPHEN: Final[str]
HYPHEN: Final[str]
SPACE: Final[str]
BREAKING_SPACE_SYMBOLS: Final[list[str]]
BREAKING_SPACE_SYMBOLS_STR: Final[str]
NBSP: Final[str]
NEWLINE: Final[str]
FORM_FEED: Final[str]
@@ -128,7 +130,7 @@ class CurrentLine:
def trim_trailing_spaces(self) -> None: ...
def manual_break(self, align: Align, trailing_nl: bool = False, trailing_form_feed: bool = False) -> TextLine: ...
def automatic_break_possible(self) -> bool: ...
def automatic_break(self, align: Align): ...
def automatic_break(self, align: Align) -> tuple[Incomplete, Incomplete, TextLine]: ...
class MultiLineBreak:
fragments: Sequence[Fragment]
@@ -153,4 +155,4 @@ class MultiLineBreak:
line_height: float = 1.0,
skip_leading_spaces: bool = False,
) -> None: ...
def get_line(self): ...
def get_line(self) -> TextLine: ...

View File

@@ -105,7 +105,7 @@ class Cell:
class RowLayoutInfo:
height: int
pagebreak_height: float
rendered_height: dict[Incomplete, Incomplete]
rendered_heights: dict[Incomplete, Incomplete]
merged_heights: list[Incomplete]
@dataclass(frozen=True)

View File

@@ -1,4 +1,5 @@
from _typeshed import Incomplete
from os import PathLike
from typing import Any
__author__: str
@@ -14,7 +15,10 @@ class FlexTemplate:
elements: Any
keys: Any
def load_elements(self, elements) -> None: ...
def parse_csv(self, infile, delimiter: str = ",", decimal_sep: str = ".", encoding: Incomplete | None = None): ...
def parse_json(self, infile: PathLike[Any], encoding: str = "utf-8") -> None: ...
def parse_csv(
self, infile: PathLike[Any], delimiter: str = ",", decimal_sep: str = ".", encoding: str | None = None
) -> None: ...
def __setitem__(self, name, value) -> None: ...
set: Any
def __contains__(self, name): ...

View File

@@ -5,6 +5,7 @@ from typing_extensions import Self
from .enums import Align, WrapMode
from .image_datastructures import RasterImageInfo, VectorImageInfo, _TextAlign
from .line_break import Fragment, TextLine
class Extents(NamedTuple):
left: float
@@ -22,14 +23,24 @@ class LineWrapper(NamedTuple):
first_line: bool = False
last_line: bool = False
class Bullet:
fragments: Sequence[Fragment]
text_line: TextLine
r_margin: float
rendered_flag: bool
def __init__(self, bullet_fragments: Sequence[Fragment], text_line: TextLine, bullet_r_margin: float) -> None: ...
def get_fragments_width(self) -> float: ...
class Paragraph:
pdf: Incomplete
text_align: Align
line_height: Incomplete
top_margin: Incomplete
bottom_margin: Incomplete
skip_leading_spaces: Incomplete
indent: float
skip_leading_spaces: bool
wrapmode: Incomplete
bullet: Bullet | None
def __init__(
self,
@@ -38,12 +49,18 @@ class Paragraph:
line_height: Incomplete | None = None,
top_margin: float = 0,
bottom_margin: float = 0,
indent: float = 0,
bullet_r_margin: float | None = None,
bullet_string: str = "",
skip_leading_spaces: bool = False,
wrapmode: WrapMode | None = None,
) -> None: ...
def __enter__(self): ...
def __exit__(self, exc_type, exc_value, traceback) -> None: ...
def write(self, text: str, link: Incomplete | None = None): ...
def generate_bullet_frags_and_tl(
self, bullet_string: str, bullet_r_margin: float
) -> tuple[tuple[Fragment, ...], TextLine] | None: ...
def ln(self, h: float | None = None) -> None: ...
def build_lines(self, print_sh: bool) -> list[LineWrapper]: ...
@@ -113,8 +130,11 @@ class ParagraphCollectorMixin:
skip_leading_spaces: bool = False,
top_margin: int = 0,
bottom_margin: int = 0,
indent: int = 0,
bullet_string: str = "",
bullet_r_margin: float | None = None,
wrapmode: WrapMode | None = None,
): ...
) -> Paragraph: ...
def end_paragraph(self) -> None: ...
def image(
self,

View File

@@ -0,0 +1,172 @@
from enum import IntEnum
from typing import Final
class UnicodeScript(IntEnum):
COMMON = 0
LATIN = 1
GREEK = 2
CYRILLIC = 3
ARMENIAN = 4
HEBREW = 5
ARABIC = 6
SYRIAC = 7
THAANA = 8
DEVANAGARI = 9
BENGALI = 10
GURMUKHI = 11
GUJARATI = 12
ORIYA = 13
TAMIL = 14
TELUGU = 15
KANNADA = 16
MALAYALAM = 17
SINHALA = 18
THAI = 19
LAO = 20
TIBETAN = 21
MYANMAR = 22
GEORGIAN = 23
HANGUL = 24
ETHIOPIC = 25
CHEROKEE = 26
CANADIAN_ABORIGINAL = 27
OGHAM = 28
RUNIC = 29
KHMER = 30
MONGOLIAN = 31
HIRAGANA = 32
KATAKANA = 33
BOPOMOFO = 34
HAN = 35
YI = 36
OLD_ITALIC = 37
GOTHIC = 38
DESERET = 39
INHERITED = 40
TAGALOG = 41
HANUNOO = 42
BUHID = 43
TAGBANWA = 44
LIMBU = 45
TAI_LE = 46
LINEAR_B = 47
UGARITIC = 48
SHAVIAN = 49
OSMANYA = 50
CYPRIOT = 51
BRAILLE = 52
BUGINESE = 53
COPTIC = 54
NEW_TAI_LUE = 55
GLAGOLITIC = 56
TIFINAGH = 57
SYLOTI_NAGRI = 58
OLD_PERSIAN = 59
KHAROSHTHI = 60
BALINESE = 61
CUNEIFORM = 62
PHOENICIAN = 63
PHAGS_PA = 64
NKO = 65
SUNDANESE = 66
LEPCHA = 67
OL_CHIKI = 68
VAI = 69
SAURASHTRA = 70
KAYAH_LI = 71
REJANG = 72
LYCIAN = 73
CARIAN = 74
LYDIAN = 75
CHAM = 76
TAI_THAM = 77
TAI_VIET = 78
AVESTAN = 79
EGYPTIAN_HIEROGLYPHS = 80
SAMARITAN = 81
LISU = 82
BAMUM = 83
JAVANESE = 84
MEETEI_MAYEK = 85
IMPERIAL_ARAMAIC = 86
OLD_SOUTH_ARABIAN = 87
INSCRIPTIONAL_PARTHIAN = 88
INSCRIPTIONAL_PAHLAVI = 89
OLD_TURKIC = 90
KAITHI = 91
BATAK = 92
BRAHMI = 93
MANDAIC = 94
CHAKMA = 95
MEROITIC_CURSIVE = 96
MEROITIC_HIEROGLYPHS = 97
MIAO = 98
SHARADA = 99
SORA_SOMPENG = 100
TAKRI = 101
CAUCASIAN_ALBANIAN = 102
BASSA_VAH = 103
DUPLOYAN = 104
ELBASAN = 105
GRANTHA = 106
PAHAWH_HMONG = 107
KHOJKI = 108
LINEAR_A = 109
MAHAJANI = 110
MANICHAEAN = 111
MENDE_KIKAKUI = 112
MODI = 113
MRO = 114
OLD_NORTH_ARABIAN = 115
NABATAEAN = 116
PALMYRENE = 117
PAU_CIN_HAU = 118
OLD_PERMIC = 119
PSALTER_PAHLAVI = 120
SIDDHAM = 121
KHUDAWADI = 122
TIRHUTA = 123
WARANG_CITI = 124
AHOM = 125
ANATOLIAN_HIEROGLYPHS = 126
HATRAN = 127
MULTANI = 128
OLD_HUNGARIAN = 129
SIGNWRITING = 130
ADLAM = 131
BHAIKSUKI = 132
MARCHEN = 133
NEWA = 134
OSAGE = 135
TANGUT = 136
MASARAM_GONDI = 137
NUSHU = 138
SOYOMBO = 139
ZANABAZAR_SQUARE = 140
DOGRA = 141
GUNJALA_GONDI = 142
MAKASAR = 143
MEDEFAIDRIN = 144
HANIFI_ROHINGYA = 145
SOGDIAN = 146
OLD_SOGDIAN = 147
ELYMAIC = 148
NANDINAGARI = 149
NYIAKENG_PUACHUE_HMONG = 150
WANCHO = 151
CHORASMIAN = 152
DIVES_AKURU = 153
KHITAN_SMALL_SCRIPT = 154
YEZIDI = 155
CYPRO_MINOAN = 156
OLD_UYGHUR = 157
TANGSA = 158
TOTO = 159
VITHKUQI = 160
KAWI = 161
NAG_MUNDARI = 162
UNKNOWN = 999
UNICODE_RANGE_TO_SCRIPT: Final[tuple[tuple[int, int, int]]]
def get_unicode_script(char: str) -> UnicodeScript: ...