diff --git a/data/interfaces/default/stream_data.html b/data/interfaces/default/stream_data.html
index 9e42189b..a40bc54a 100644
--- a/data/interfaces/default/stream_data.html
+++ b/data/interfaces/default/stream_data.html
@@ -68,14 +68,14 @@ DOCUMENTATION :: END
-
- |
-
- Stream Details
- |
+ |
Source Details
|
+ |
+
+ Stream Details
+ |
@@ -85,38 +85,46 @@ DOCUMENTATION :: END
Media
|
+
|
+
|
+
|
Bitrate |
- ${data['stream_bitrate']} ${'kbps' if data['stream_bitrate'] else ''} |
${data['bitrate']} ${'kbps' if data['bitrate'] else ''} |
+ |
+ ${data['stream_bitrate']} ${'kbps' if data['stream_bitrate'] else ''} |
% if data['media_type'] != 'track':
Resolution |
- ${data['stream_video_full_resolution']} |
${data['video_full_resolution']} |
+ |
+ ${data['stream_video_full_resolution']} |
% endif
Quality |
- ${data['quality_profile']} |
- |
+ |
+ ${data['quality_profile']} |
% if data['optimized_version'] == 1:
Optimized Version |
- - |
${data['optimized_version_profile']} (${data['optimized_version_title']}) |
+ |
+ - |
% endif
% if data['synced_version'] == 1:
Synced Version |
- - |
${data['synced_version_profile']} |
+ |
+ - |
% endif
@@ -127,6 +135,8 @@ DOCUMENTATION :: END
Container
|
+
|
+
|
${data['stream_container_decision']}
|
@@ -135,8 +145,9 @@ DOCUMENTATION :: END
Container |
- ${data['stream_container'].upper()} |
${data['container'].upper()} |
+ |
+ ${data['stream_container'].upper()} |
@@ -147,6 +158,8 @@ DOCUMENTATION :: END
Video
|
+
|
+
|
${data['stream_video_decision']}
|
@@ -155,38 +168,45 @@ DOCUMENTATION :: END
Codec |
- ${data['stream_video_codec'].upper()} ${'(HW)' if data['transcode_hw_encoding'] else ''} |
${data['video_codec'].upper()} ${'(HW)' if data['transcode_hw_decoding'] else ''} |
+ |
+ ${data['stream_video_codec'].upper()} ${'(HW)' if data['transcode_hw_encoding'] else ''} |
Bitrate |
- ${data['stream_video_bitrate']} ${'kbps' if data['stream_video_bitrate'] else ''} |
${data['video_bitrate']} ${'kbps' if data['video_bitrate'] else ''} |
+ |
+ ${data['stream_video_bitrate']} ${'kbps' if data['stream_video_bitrate'] else ''} |
Width |
- ${data['stream_video_width']} |
${data['video_width']} |
+ |
+ ${data['stream_video_width']} |
Height |
- ${data['stream_video_height']} |
${data['video_height']} |
+ |
+ ${data['stream_video_height']} |
Framerate |
- ${data['stream_video_framerate']} |
${data['video_framerate']} |
+ |
+ ${data['stream_video_framerate']} |
Dynamic Range |
- ${data['stream_video_dynamic_range']} |
${data['video_dynamic_range']} |
+ |
+ ${data['stream_video_dynamic_range']} |
Aspect Ratio |
- - |
${data['aspect_ratio']} |
+ |
+ - |
@@ -197,6 +217,8 @@ DOCUMENTATION :: END
Audio
|
+
|
+
|
${data['stream_audio_decision']}
|
@@ -205,23 +227,27 @@ DOCUMENTATION :: END
Codec |
- ${AUDIO_CODEC_OVERRIDES.get(data['stream_audio_codec'], data['stream_audio_codec'].upper())} |
${AUDIO_CODEC_OVERRIDES.get(data['audio_codec'], data['audio_codec'].upper())} |
+ |
+ ${AUDIO_CODEC_OVERRIDES.get(data['stream_audio_codec'], data['stream_audio_codec'].upper())} |
Bitrate |
- ${data['stream_audio_bitrate']} ${'kbps' if data['stream_audio_bitrate'] else ''} |
${data['audio_bitrate']} ${'kbps' if data['audio_bitrate'] else ''} |
+ |
+ ${data['stream_audio_bitrate']} ${'kbps' if data['stream_audio_bitrate'] else ''} |
Channels |
- ${data['stream_audio_channels']} |
${data['audio_channels']} |
+ |
+ ${data['stream_audio_channels']} |
Language |
- - |
${data['audio_language'] or 'Unknown'} |
+ |
+ - |
@@ -233,6 +259,8 @@ DOCUMENTATION :: END
Subtitles
|
+
|
+
|
${'direct play' if data['stream_subtitle_decision'] not in ('transcode', 'copy', 'burn') else data['stream_subtitle_decision']}
|
@@ -241,19 +269,22 @@ DOCUMENTATION :: END
Codec |
- ${data['stream_subtitle_codec'].upper() or '-'} |
${data['subtitle_codec'].upper()} |
+ |
+ ${data['stream_subtitle_codec'].upper() or '-'} |
Language |
- - |
${data['subtitle_language'] or 'Unknown'} |
+ |
+ - |
% if data['subtitle_forced']:
Forced |
- - |
${bool(data['subtitle_forced'])} |
+ |
+ - |
% endif
diff --git a/lib/backports/zoneinfo/__init__.py b/lib/backports/zoneinfo/__init__.py
deleted file mode 100644
index 861fc48e..00000000
--- a/lib/backports/zoneinfo/__init__.py
+++ /dev/null
@@ -1,49 +0,0 @@
-__all__ = [
- "ZoneInfo",
- "reset_tzpath",
- "available_timezones",
- "TZPATH",
- "ZoneInfoNotFoundError",
- "InvalidTZPathWarning",
-]
-import sys
-
-from . import _tzpath
-from ._common import ZoneInfoNotFoundError
-from ._version import __version__
-
-try:
- from ._czoneinfo import ZoneInfo
-except ImportError: # pragma: nocover
- from ._zoneinfo import ZoneInfo
-
-reset_tzpath = _tzpath.reset_tzpath
-available_timezones = _tzpath.available_timezones
-InvalidTZPathWarning = _tzpath.InvalidTZPathWarning
-
-if sys.version_info < (3, 7):
- # Module-level __getattr__ was added in Python 3.7, so instead of lazily
- # populating TZPATH on every access, we will register a callback with
- # reset_tzpath to update the top-level tuple.
- TZPATH = _tzpath.TZPATH
-
- def _tzpath_callback(new_tzpath):
- global TZPATH
- TZPATH = new_tzpath
-
- _tzpath.TZPATH_CALLBACKS.append(_tzpath_callback)
- del _tzpath_callback
-
-else:
-
- def __getattr__(name):
- if name == "TZPATH":
- return _tzpath.TZPATH
- else:
- raise AttributeError(
- f"module {__name__!r} has no attribute {name!r}"
- )
-
-
-def __dir__():
- return sorted(list(globals()) + ["TZPATH"])
diff --git a/lib/backports/zoneinfo/__init__.pyi b/lib/backports/zoneinfo/__init__.pyi
deleted file mode 100644
index 6e56abf2..00000000
--- a/lib/backports/zoneinfo/__init__.pyi
+++ /dev/null
@@ -1,45 +0,0 @@
-import os
-import typing
-from datetime import datetime, tzinfo
-from typing import (
- Any,
- Iterable,
- Optional,
- Protocol,
- Sequence,
- Set,
- Type,
- Union,
-)
-
-_T = typing.TypeVar("_T", bound="ZoneInfo")
-
-class _IOBytes(Protocol):
- def read(self, __size: int) -> bytes: ...
- def seek(self, __size: int, __whence: int = ...) -> Any: ...
-
-class ZoneInfo(tzinfo):
- @property
- def key(self) -> str: ...
- def __init__(self, key: str) -> None: ...
- @classmethod
- def no_cache(cls: Type[_T], key: str) -> _T: ...
- @classmethod
- def from_file(
- cls: Type[_T], __fobj: _IOBytes, key: Optional[str] = ...
- ) -> _T: ...
- @classmethod
- def clear_cache(cls, *, only_keys: Iterable[str] = ...) -> None: ...
-
-# Note: Both here and in clear_cache, the types allow the use of `str` where
-# a sequence of strings is required. This should be remedied if a solution
-# to this typing bug is found: https://github.com/python/typing/issues/256
-def reset_tzpath(
- to: Optional[Sequence[Union[os.PathLike, str]]] = ...
-) -> None: ...
-def available_timezones() -> Set[str]: ...
-
-TZPATH: Sequence[str]
-
-class ZoneInfoNotFoundError(KeyError): ...
-class InvalidTZPathWarning(RuntimeWarning): ...
diff --git a/lib/backports/zoneinfo/_common.py b/lib/backports/zoneinfo/_common.py
deleted file mode 100644
index 27a6ab02..00000000
--- a/lib/backports/zoneinfo/_common.py
+++ /dev/null
@@ -1,171 +0,0 @@
-import struct
-
-
-def load_tzdata(key):
- try:
- import importlib.resources as importlib_resources
- except ImportError:
- import importlib_resources
-
- components = key.split("/")
- package_name = ".".join(["tzdata.zoneinfo"] + components[:-1])
- resource_name = components[-1]
-
- try:
- return importlib_resources.open_binary(package_name, resource_name)
- except (ImportError, FileNotFoundError, UnicodeEncodeError):
- # There are three types of exception that can be raised that all amount
- # to "we cannot find this key":
- #
- # ImportError: If package_name doesn't exist (e.g. if tzdata is not
- # installed, or if there's an error in the folder name like
- # Amrica/New_York)
- # FileNotFoundError: If resource_name doesn't exist in the package
- # (e.g. Europe/Krasnoy)
- # UnicodeEncodeError: If package_name or resource_name are not UTF-8,
- # such as keys containing a surrogate character.
- raise ZoneInfoNotFoundError(f"No time zone found with key {key}")
-
-
-def load_data(fobj):
- header = _TZifHeader.from_file(fobj)
-
- if header.version == 1:
- time_size = 4
- time_type = "l"
- else:
- # Version 2+ has 64-bit integer transition times
- time_size = 8
- time_type = "q"
-
- # Version 2+ also starts with a Version 1 header and data, which
- # we need to skip now
- skip_bytes = (
- header.timecnt * 5 # Transition times and types
- + header.typecnt * 6 # Local time type records
- + header.charcnt # Time zone designations
- + header.leapcnt * 8 # Leap second records
- + header.isstdcnt # Standard/wall indicators
- + header.isutcnt # UT/local indicators
- )
-
- fobj.seek(skip_bytes, 1)
-
- # Now we need to read the second header, which is not the same
- # as the first
- header = _TZifHeader.from_file(fobj)
-
- typecnt = header.typecnt
- timecnt = header.timecnt
- charcnt = header.charcnt
-
- # The data portion starts with timecnt transitions and indices
- if timecnt:
- trans_list_utc = struct.unpack(
- f">{timecnt}{time_type}", fobj.read(timecnt * time_size)
- )
- trans_idx = struct.unpack(f">{timecnt}B", fobj.read(timecnt))
- else:
- trans_list_utc = ()
- trans_idx = ()
-
- # Read the ttinfo struct, (utoff, isdst, abbrind)
- if typecnt:
- utcoff, isdst, abbrind = zip(
- *(struct.unpack(">lbb", fobj.read(6)) for i in range(typecnt))
- )
- else:
- utcoff = ()
- isdst = ()
- abbrind = ()
-
- # Now read the abbreviations. They are null-terminated strings, indexed
- # not by position in the array but by position in the unsplit
- # abbreviation string. I suppose this makes more sense in C, which uses
- # null to terminate the strings, but it's inconvenient here...
- abbr_vals = {}
- abbr_chars = fobj.read(charcnt)
-
- def get_abbr(idx):
- # Gets a string starting at idx and running until the next \x00
- #
- # We cannot pre-populate abbr_vals by splitting on \x00 because there
- # are some zones that use subsets of longer abbreviations, like so:
- #
- # LMT\x00AHST\x00HDT\x00
- #
- # Where the idx to abbr mapping should be:
- #
- # {0: "LMT", 4: "AHST", 5: "HST", 9: "HDT"}
- if idx not in abbr_vals:
- span_end = abbr_chars.find(b"\x00", idx)
- abbr_vals[idx] = abbr_chars[idx:span_end].decode()
-
- return abbr_vals[idx]
-
- abbr = tuple(get_abbr(idx) for idx in abbrind)
-
- # The remainder of the file consists of leap seconds (currently unused) and
- # the standard/wall and ut/local indicators, which are metadata we don't need.
- # In version 2 files, we need to skip the unnecessary data to get at the TZ string:
- if header.version >= 2:
- # Each leap second record has size (time_size + 4)
- skip_bytes = header.isutcnt + header.isstdcnt + header.leapcnt * 12
- fobj.seek(skip_bytes, 1)
-
- c = fobj.read(1) # Should be \n
- assert c == b"\n", c
-
- tz_bytes = b""
- while True:
- c = fobj.read(1)
- if c == b"\n":
- break
- tz_bytes += c
-
- tz_str = tz_bytes
- else:
- tz_str = None
-
- return trans_idx, trans_list_utc, utcoff, isdst, abbr, tz_str
-
-
-class _TZifHeader:
- __slots__ = [
- "version",
- "isutcnt",
- "isstdcnt",
- "leapcnt",
- "timecnt",
- "typecnt",
- "charcnt",
- ]
-
- def __init__(self, *args):
- assert len(self.__slots__) == len(args)
- for attr, val in zip(self.__slots__, args):
- setattr(self, attr, val)
-
- @classmethod
- def from_file(cls, stream):
- # The header starts with a 4-byte "magic" value
- if stream.read(4) != b"TZif":
- raise ValueError("Invalid TZif file: magic not found")
-
- _version = stream.read(1)
- if _version == b"\x00":
- version = 1
- else:
- version = int(_version)
- stream.read(15)
-
- args = (version,)
-
- # Slots are defined in the order that the bytes are arranged
- args = args + struct.unpack(">6l", stream.read(24))
-
- return cls(*args)
-
-
-class ZoneInfoNotFoundError(KeyError):
- """Exception raised when a ZoneInfo key is not found."""
diff --git a/lib/backports/zoneinfo/_tzpath.py b/lib/backports/zoneinfo/_tzpath.py
deleted file mode 100644
index 9baaf6bc..00000000
--- a/lib/backports/zoneinfo/_tzpath.py
+++ /dev/null
@@ -1,207 +0,0 @@
-import os
-import sys
-
-PY36 = sys.version_info < (3, 7)
-
-
-def reset_tzpath(to=None):
- global TZPATH
-
- tzpaths = to
- if tzpaths is not None:
- if isinstance(tzpaths, (str, bytes)):
- raise TypeError(
- f"tzpaths must be a list or tuple, "
- + f"not {type(tzpaths)}: {tzpaths!r}"
- )
-
- if not all(map(os.path.isabs, tzpaths)):
- raise ValueError(_get_invalid_paths_message(tzpaths))
- base_tzpath = tzpaths
- else:
- env_var = os.environ.get("PYTHONTZPATH", None)
- if env_var is not None:
- base_tzpath = _parse_python_tzpath(env_var)
- elif sys.platform != "win32":
- base_tzpath = [
- "/usr/share/zoneinfo",
- "/usr/lib/zoneinfo",
- "/usr/share/lib/zoneinfo",
- "/etc/zoneinfo",
- ]
-
- base_tzpath.sort(key=lambda x: not os.path.exists(x))
- else:
- base_tzpath = ()
-
- TZPATH = tuple(base_tzpath)
-
- if TZPATH_CALLBACKS:
- for callback in TZPATH_CALLBACKS:
- callback(TZPATH)
-
-
-def _parse_python_tzpath(env_var):
- if not env_var:
- return ()
-
- raw_tzpath = env_var.split(os.pathsep)
- new_tzpath = tuple(filter(os.path.isabs, raw_tzpath))
-
- # If anything has been filtered out, we will warn about it
- if len(new_tzpath) != len(raw_tzpath):
- import warnings
-
- msg = _get_invalid_paths_message(raw_tzpath)
-
- warnings.warn(
- "Invalid paths specified in PYTHONTZPATH environment variable."
- + msg,
- InvalidTZPathWarning,
- )
-
- return new_tzpath
-
-
-def _get_invalid_paths_message(tzpaths):
- invalid_paths = (path for path in tzpaths if not os.path.isabs(path))
-
- prefix = "\n "
- indented_str = prefix + prefix.join(invalid_paths)
-
- return (
- "Paths should be absolute but found the following relative paths:"
- + indented_str
- )
-
-
-if sys.version_info < (3, 8):
-
- def _isfile(path):
- # bpo-33721: In Python 3.8 non-UTF8 paths return False rather than
- # raising an error. See https://bugs.python.org/issue33721
- try:
- return os.path.isfile(path)
- except ValueError:
- return False
-
-
-else:
- _isfile = os.path.isfile
-
-
-def find_tzfile(key):
- """Retrieve the path to a TZif file from a key."""
- _validate_tzfile_path(key)
- for search_path in TZPATH:
- filepath = os.path.join(search_path, key)
- if _isfile(filepath):
- return filepath
-
- return None
-
-
-_TEST_PATH = os.path.normpath(os.path.join("_", "_"))[:-1]
-
-
-def _validate_tzfile_path(path, _base=_TEST_PATH):
- if os.path.isabs(path):
- raise ValueError(
- f"ZoneInfo keys may not be absolute paths, got: {path}"
- )
-
- # We only care about the kinds of path normalizations that would change the
- # length of the key - e.g. a/../b -> a/b, or a/b/ -> a/b. On Windows,
- # normpath will also change from a/b to a\b, but that would still preserve
- # the length.
- new_path = os.path.normpath(path)
- if len(new_path) != len(path):
- raise ValueError(
- f"ZoneInfo keys must be normalized relative paths, got: {path}"
- )
-
- resolved = os.path.normpath(os.path.join(_base, new_path))
- if not resolved.startswith(_base):
- raise ValueError(
- f"ZoneInfo keys must refer to subdirectories of TZPATH, got: {path}"
- )
-
-
-del _TEST_PATH
-
-
-def available_timezones():
- """Returns a set containing all available time zones.
-
- .. caution::
-
- This may attempt to open a large number of files, since the best way to
- determine if a given file on the time zone search path is to open it
- and check for the "magic string" at the beginning.
- """
- try:
- from importlib import resources
- except ImportError:
- import importlib_resources as resources
-
- valid_zones = set()
-
- # Start with loading from the tzdata package if it exists: this has a
- # pre-assembled list of zones that only requires opening one file.
- try:
- with resources.open_text("tzdata", "zones") as f:
- for zone in f:
- zone = zone.strip()
- if zone:
- valid_zones.add(zone)
- except (ImportError, FileNotFoundError):
- pass
-
- def valid_key(fpath):
- try:
- with open(fpath, "rb") as f:
- return f.read(4) == b"TZif"
- except Exception: # pragma: nocover
- return False
-
- for tz_root in TZPATH:
- if not os.path.exists(tz_root):
- continue
-
- for root, dirnames, files in os.walk(tz_root):
- if root == tz_root:
- # right/ and posix/ are special directories and shouldn't be
- # included in the output of available zones
- if "right" in dirnames:
- dirnames.remove("right")
- if "posix" in dirnames:
- dirnames.remove("posix")
-
- for file in files:
- fpath = os.path.join(root, file)
-
- key = os.path.relpath(fpath, start=tz_root)
- if os.sep != "/": # pragma: nocover
- key = key.replace(os.sep, "/")
-
- if not key or key in valid_zones:
- continue
-
- if valid_key(fpath):
- valid_zones.add(key)
-
- if "posixrules" in valid_zones:
- # posixrules is a special symlink-only time zone where it exists, it
- # should not be included in the output
- valid_zones.remove("posixrules")
-
- return valid_zones
-
-
-class InvalidTZPathWarning(RuntimeWarning):
- """Warning raised if an invalid path is specified in PYTHONTZPATH."""
-
-
-TZPATH = ()
-TZPATH_CALLBACKS = []
-reset_tzpath()
diff --git a/lib/backports/zoneinfo/_version.py b/lib/backports/zoneinfo/_version.py
deleted file mode 100644
index 3ced3581..00000000
--- a/lib/backports/zoneinfo/_version.py
+++ /dev/null
@@ -1 +0,0 @@
-__version__ = "0.2.1"
diff --git a/lib/backports/zoneinfo/_zoneinfo.py b/lib/backports/zoneinfo/_zoneinfo.py
deleted file mode 100644
index c15a5534..00000000
--- a/lib/backports/zoneinfo/_zoneinfo.py
+++ /dev/null
@@ -1,754 +0,0 @@
-import bisect
-import calendar
-import collections
-import functools
-import re
-import weakref
-from datetime import datetime, timedelta, tzinfo
-
-from . import _common, _tzpath
-
-EPOCH = datetime(1970, 1, 1)
-EPOCHORDINAL = datetime(1970, 1, 1).toordinal()
-
-# It is relatively expensive to construct new timedelta objects, and in most
-# cases we're looking at the same deltas, like integer numbers of hours, etc.
-# To improve speed and memory use, we'll keep a dictionary with references
-# to the ones we've already used so far.
-#
-# Loading every time zone in the 2020a version of the time zone database
-# requires 447 timedeltas, which requires approximately the amount of space
-# that ZoneInfo("America/New_York") with 236 transitions takes up, so we will
-# set the cache size to 512 so that in the common case we always get cache
-# hits, but specifically crafted ZoneInfo objects don't leak arbitrary amounts
-# of memory.
-@functools.lru_cache(maxsize=512)
-def _load_timedelta(seconds):
- return timedelta(seconds=seconds)
-
-
-class ZoneInfo(tzinfo):
- _strong_cache_size = 8
- _strong_cache = collections.OrderedDict()
- _weak_cache = weakref.WeakValueDictionary()
- __module__ = "backports.zoneinfo"
-
- def __init_subclass__(cls):
- cls._strong_cache = collections.OrderedDict()
- cls._weak_cache = weakref.WeakValueDictionary()
-
- def __new__(cls, key):
- instance = cls._weak_cache.get(key, None)
- if instance is None:
- instance = cls._weak_cache.setdefault(key, cls._new_instance(key))
- instance._from_cache = True
-
- # Update the "strong" cache
- cls._strong_cache[key] = cls._strong_cache.pop(key, instance)
-
- if len(cls._strong_cache) > cls._strong_cache_size:
- cls._strong_cache.popitem(last=False)
-
- return instance
-
- @classmethod
- def no_cache(cls, key):
- obj = cls._new_instance(key)
- obj._from_cache = False
-
- return obj
-
- @classmethod
- def _new_instance(cls, key):
- obj = super().__new__(cls)
- obj._key = key
- obj._file_path = obj._find_tzfile(key)
-
- if obj._file_path is not None:
- file_obj = open(obj._file_path, "rb")
- else:
- file_obj = _common.load_tzdata(key)
-
- with file_obj as f:
- obj._load_file(f)
-
- return obj
-
- @classmethod
- def from_file(cls, fobj, key=None):
- obj = super().__new__(cls)
- obj._key = key
- obj._file_path = None
- obj._load_file(fobj)
- obj._file_repr = repr(fobj)
-
- # Disable pickling for objects created from files
- obj.__reduce__ = obj._file_reduce
-
- return obj
-
- @classmethod
- def clear_cache(cls, *, only_keys=None):
- if only_keys is not None:
- for key in only_keys:
- cls._weak_cache.pop(key, None)
- cls._strong_cache.pop(key, None)
-
- else:
- cls._weak_cache.clear()
- cls._strong_cache.clear()
-
- @property
- def key(self):
- return self._key
-
- def utcoffset(self, dt):
- return self._find_trans(dt).utcoff
-
- def dst(self, dt):
- return self._find_trans(dt).dstoff
-
- def tzname(self, dt):
- return self._find_trans(dt).tzname
-
- def fromutc(self, dt):
- """Convert from datetime in UTC to datetime in local time"""
-
- if not isinstance(dt, datetime):
- raise TypeError("fromutc() requires a datetime argument")
- if dt.tzinfo is not self:
- raise ValueError("dt.tzinfo is not self")
-
- timestamp = self._get_local_timestamp(dt)
- num_trans = len(self._trans_utc)
-
- if num_trans >= 1 and timestamp < self._trans_utc[0]:
- tti = self._tti_before
- fold = 0
- elif (
- num_trans == 0 or timestamp > self._trans_utc[-1]
- ) and not isinstance(self._tz_after, _ttinfo):
- tti, fold = self._tz_after.get_trans_info_fromutc(
- timestamp, dt.year
- )
- elif num_trans == 0:
- tti = self._tz_after
- fold = 0
- else:
- idx = bisect.bisect_right(self._trans_utc, timestamp)
-
- if num_trans > 1 and timestamp >= self._trans_utc[1]:
- tti_prev, tti = self._ttinfos[idx - 2 : idx]
- elif timestamp > self._trans_utc[-1]:
- tti_prev = self._ttinfos[-1]
- tti = self._tz_after
- else:
- tti_prev = self._tti_before
- tti = self._ttinfos[0]
-
- # Detect fold
- shift = tti_prev.utcoff - tti.utcoff
- fold = shift.total_seconds() > timestamp - self._trans_utc[idx - 1]
- dt += tti.utcoff
- if fold:
- return dt.replace(fold=1)
- else:
- return dt
-
- def _find_trans(self, dt):
- if dt is None:
- if self._fixed_offset:
- return self._tz_after
- else:
- return _NO_TTINFO
-
- ts = self._get_local_timestamp(dt)
-
- lt = self._trans_local[dt.fold]
-
- num_trans = len(lt)
-
- if num_trans and ts < lt[0]:
- return self._tti_before
- elif not num_trans or ts > lt[-1]:
- if isinstance(self._tz_after, _TZStr):
- return self._tz_after.get_trans_info(ts, dt.year, dt.fold)
- else:
- return self._tz_after
- else:
- # idx is the transition that occurs after this timestamp, so we
- # subtract off 1 to get the current ttinfo
- idx = bisect.bisect_right(lt, ts) - 1
- assert idx >= 0
- return self._ttinfos[idx]
-
- def _get_local_timestamp(self, dt):
- return (
- (dt.toordinal() - EPOCHORDINAL) * 86400
- + dt.hour * 3600
- + dt.minute * 60
- + dt.second
- )
-
- def __str__(self):
- if self._key is not None:
- return f"{self._key}"
- else:
- return repr(self)
-
- def __repr__(self):
- if self._key is not None:
- return f"{self.__class__.__name__}(key={self._key!r})"
- else:
- return f"{self.__class__.__name__}.from_file({self._file_repr})"
-
- def __reduce__(self):
- return (self.__class__._unpickle, (self._key, self._from_cache))
-
- def _file_reduce(self):
- import pickle
-
- raise pickle.PicklingError(
- "Cannot pickle a ZoneInfo file created from a file stream."
- )
-
- @classmethod
- def _unpickle(cls, key, from_cache):
- if from_cache:
- return cls(key)
- else:
- return cls.no_cache(key)
-
- def _find_tzfile(self, key):
- return _tzpath.find_tzfile(key)
-
- def _load_file(self, fobj):
- # Retrieve all the data as it exists in the zoneinfo file
- trans_idx, trans_utc, utcoff, isdst, abbr, tz_str = _common.load_data(
- fobj
- )
-
- # Infer the DST offsets (needed for .dst()) from the data
- dstoff = self._utcoff_to_dstoff(trans_idx, utcoff, isdst)
-
- # Convert all the transition times (UTC) into "seconds since 1970-01-01 local time"
- trans_local = self._ts_to_local(trans_idx, trans_utc, utcoff)
-
- # Construct `_ttinfo` objects for each transition in the file
- _ttinfo_list = [
- _ttinfo(
- _load_timedelta(utcoffset), _load_timedelta(dstoffset), tzname
- )
- for utcoffset, dstoffset, tzname in zip(utcoff, dstoff, abbr)
- ]
-
- self._trans_utc = trans_utc
- self._trans_local = trans_local
- self._ttinfos = [_ttinfo_list[idx] for idx in trans_idx]
-
- # Find the first non-DST transition
- for i in range(len(isdst)):
- if not isdst[i]:
- self._tti_before = _ttinfo_list[i]
- break
- else:
- if self._ttinfos:
- self._tti_before = self._ttinfos[0]
- else:
- self._tti_before = None
-
- # Set the "fallback" time zone
- if tz_str is not None and tz_str != b"":
- self._tz_after = _parse_tz_str(tz_str.decode())
- else:
- if not self._ttinfos and not _ttinfo_list:
- raise ValueError("No time zone information found.")
-
- if self._ttinfos:
- self._tz_after = self._ttinfos[-1]
- else:
- self._tz_after = _ttinfo_list[-1]
-
- # Determine if this is a "fixed offset" zone, meaning that the output
- # of the utcoffset, dst and tzname functions does not depend on the
- # specific datetime passed.
- #
- # We make three simplifying assumptions here:
- #
- # 1. If _tz_after is not a _ttinfo, it has transitions that might
- # actually occur (it is possible to construct TZ strings that
- # specify STD and DST but no transitions ever occur, such as
- # AAA0BBB,0/0,J365/25).
- # 2. If _ttinfo_list contains more than one _ttinfo object, the objects
- # represent different offsets.
- # 3. _ttinfo_list contains no unused _ttinfos (in which case an
- # otherwise fixed-offset zone with extra _ttinfos defined may
- # appear to *not* be a fixed offset zone).
- #
- # Violations to these assumptions would be fairly exotic, and exotic
- # zones should almost certainly not be used with datetime.time (the
- # only thing that would be affected by this).
- if len(_ttinfo_list) > 1 or not isinstance(self._tz_after, _ttinfo):
- self._fixed_offset = False
- elif not _ttinfo_list:
- self._fixed_offset = True
- else:
- self._fixed_offset = _ttinfo_list[0] == self._tz_after
-
- @staticmethod
- def _utcoff_to_dstoff(trans_idx, utcoffsets, isdsts):
- # Now we must transform our ttis and abbrs into `_ttinfo` objects,
- # but there is an issue: .dst() must return a timedelta with the
- # difference between utcoffset() and the "standard" offset, but
- # the "base offset" and "DST offset" are not encoded in the file;
- # we can infer what they are from the isdst flag, but it is not
- # sufficient to to just look at the last standard offset, because
- # occasionally countries will shift both DST offset and base offset.
-
- typecnt = len(isdsts)
- dstoffs = [0] * typecnt # Provisionally assign all to 0.
- dst_cnt = sum(isdsts)
- dst_found = 0
-
- for i in range(1, len(trans_idx)):
- if dst_cnt == dst_found:
- break
-
- idx = trans_idx[i]
-
- dst = isdsts[idx]
-
- # We're only going to look at daylight saving time
- if not dst:
- continue
-
- # Skip any offsets that have already been assigned
- if dstoffs[idx] != 0:
- continue
-
- dstoff = 0
- utcoff = utcoffsets[idx]
-
- comp_idx = trans_idx[i - 1]
-
- if not isdsts[comp_idx]:
- dstoff = utcoff - utcoffsets[comp_idx]
-
- if not dstoff and idx < (typecnt - 1):
- comp_idx = trans_idx[i + 1]
-
- # If the following transition is also DST and we couldn't
- # find the DST offset by this point, we're going ot have to
- # skip it and hope this transition gets assigned later
- if isdsts[comp_idx]:
- continue
-
- dstoff = utcoff - utcoffsets[comp_idx]
-
- if dstoff:
- dst_found += 1
- dstoffs[idx] = dstoff
- else:
- # If we didn't find a valid value for a given index, we'll end up
- # with dstoff = 0 for something where `isdst=1`. This is obviously
- # wrong - one hour will be a much better guess than 0
- for idx in range(typecnt):
- if not dstoffs[idx] and isdsts[idx]:
- dstoffs[idx] = 3600
-
- return dstoffs
-
- @staticmethod
- def _ts_to_local(trans_idx, trans_list_utc, utcoffsets):
- """Generate number of seconds since 1970 *in the local time*.
-
- This is necessary to easily find the transition times in local time"""
- if not trans_list_utc:
- return [[], []]
-
- # Start with the timestamps and modify in-place
- trans_list_wall = [list(trans_list_utc), list(trans_list_utc)]
-
- if len(utcoffsets) > 1:
- offset_0 = utcoffsets[0]
- offset_1 = utcoffsets[trans_idx[0]]
- if offset_1 > offset_0:
- offset_1, offset_0 = offset_0, offset_1
- else:
- offset_0 = offset_1 = utcoffsets[0]
-
- trans_list_wall[0][0] += offset_0
- trans_list_wall[1][0] += offset_1
-
- for i in range(1, len(trans_idx)):
- offset_0 = utcoffsets[trans_idx[i - 1]]
- offset_1 = utcoffsets[trans_idx[i]]
-
- if offset_1 > offset_0:
- offset_1, offset_0 = offset_0, offset_1
-
- trans_list_wall[0][i] += offset_0
- trans_list_wall[1][i] += offset_1
-
- return trans_list_wall
-
-
-class _ttinfo:
- __slots__ = ["utcoff", "dstoff", "tzname"]
-
- def __init__(self, utcoff, dstoff, tzname):
- self.utcoff = utcoff
- self.dstoff = dstoff
- self.tzname = tzname
-
- def __eq__(self, other):
- return (
- self.utcoff == other.utcoff
- and self.dstoff == other.dstoff
- and self.tzname == other.tzname
- )
-
- def __repr__(self): # pragma: nocover
- return (
- f"{self.__class__.__name__}"
- + f"({self.utcoff}, {self.dstoff}, {self.tzname})"
- )
-
-
-_NO_TTINFO = _ttinfo(None, None, None)
-
-
-class _TZStr:
- __slots__ = (
- "std",
- "dst",
- "start",
- "end",
- "get_trans_info",
- "get_trans_info_fromutc",
- "dst_diff",
- )
-
- def __init__(
- self, std_abbr, std_offset, dst_abbr, dst_offset, start=None, end=None
- ):
- self.dst_diff = dst_offset - std_offset
- std_offset = _load_timedelta(std_offset)
- self.std = _ttinfo(
- utcoff=std_offset, dstoff=_load_timedelta(0), tzname=std_abbr
- )
-
- self.start = start
- self.end = end
-
- dst_offset = _load_timedelta(dst_offset)
- delta = _load_timedelta(self.dst_diff)
- self.dst = _ttinfo(utcoff=dst_offset, dstoff=delta, tzname=dst_abbr)
-
- # These are assertions because the constructor should only be called
- # by functions that would fail before passing start or end
- assert start is not None, "No transition start specified"
- assert end is not None, "No transition end specified"
-
- self.get_trans_info = self._get_trans_info
- self.get_trans_info_fromutc = self._get_trans_info_fromutc
-
- def transitions(self, year):
- start = self.start.year_to_epoch(year)
- end = self.end.year_to_epoch(year)
- return start, end
-
- def _get_trans_info(self, ts, year, fold):
- """Get the information about the current transition - tti"""
- start, end = self.transitions(year)
-
- # With fold = 0, the period (denominated in local time) with the
- # smaller offset starts at the end of the gap and ends at the end of
- # the fold; with fold = 1, it runs from the start of the gap to the
- # beginning of the fold.
- #
- # So in order to determine the DST boundaries we need to know both
- # the fold and whether DST is positive or negative (rare), and it
- # turns out that this boils down to fold XOR is_positive.
- if fold == (self.dst_diff >= 0):
- end -= self.dst_diff
- else:
- start += self.dst_diff
-
- if start < end:
- isdst = start <= ts < end
- else:
- isdst = not (end <= ts < start)
-
- return self.dst if isdst else self.std
-
- def _get_trans_info_fromutc(self, ts, year):
- start, end = self.transitions(year)
- start -= self.std.utcoff.total_seconds()
- end -= self.dst.utcoff.total_seconds()
-
- if start < end:
- isdst = start <= ts < end
- else:
- isdst = not (end <= ts < start)
-
- # For positive DST, the ambiguous period is one dst_diff after the end
- # of DST; for negative DST, the ambiguous period is one dst_diff before
- # the start of DST.
- if self.dst_diff > 0:
- ambig_start = end
- ambig_end = end + self.dst_diff
- else:
- ambig_start = start
- ambig_end = start - self.dst_diff
-
- fold = ambig_start <= ts < ambig_end
-
- return (self.dst if isdst else self.std, fold)
-
-
-def _post_epoch_days_before_year(year):
- """Get the number of days between 1970-01-01 and YEAR-01-01"""
- y = year - 1
- return y * 365 + y // 4 - y // 100 + y // 400 - EPOCHORDINAL
-
-
-class _DayOffset:
- __slots__ = ["d", "julian", "hour", "minute", "second"]
-
- def __init__(self, d, julian, hour=2, minute=0, second=0):
- if not (0 + julian) <= d <= 365:
- min_day = 0 + julian
- raise ValueError(f"d must be in [{min_day}, 365], not: {d}")
-
- self.d = d
- self.julian = julian
- self.hour = hour
- self.minute = minute
- self.second = second
-
- def year_to_epoch(self, year):
- days_before_year = _post_epoch_days_before_year(year)
-
- d = self.d
- if self.julian and d >= 59 and calendar.isleap(year):
- d += 1
-
- epoch = (days_before_year + d) * 86400
- epoch += self.hour * 3600 + self.minute * 60 + self.second
-
- return epoch
-
-
-class _CalendarOffset:
- __slots__ = ["m", "w", "d", "hour", "minute", "second"]
-
- _DAYS_BEFORE_MONTH = (
- -1,
- 0,
- 31,
- 59,
- 90,
- 120,
- 151,
- 181,
- 212,
- 243,
- 273,
- 304,
- 334,
- )
-
- def __init__(self, m, w, d, hour=2, minute=0, second=0):
- if not 0 < m <= 12:
- raise ValueError("m must be in (0, 12]")
-
- if not 0 < w <= 5:
- raise ValueError("w must be in (0, 5]")
-
- if not 0 <= d <= 6:
- raise ValueError("d must be in [0, 6]")
-
- self.m = m
- self.w = w
- self.d = d
- self.hour = hour
- self.minute = minute
- self.second = second
-
- @classmethod
- def _ymd2ord(cls, year, month, day):
- return (
- _post_epoch_days_before_year(year)
- + cls._DAYS_BEFORE_MONTH[month]
- + (month > 2 and calendar.isleap(year))
- + day
- )
-
- # TODO: These are not actually epoch dates as they are expressed in local time
- def year_to_epoch(self, year):
- """Calculates the datetime of the occurrence from the year"""
- # We know year and month, we need to convert w, d into day of month
- #
- # Week 1 is the first week in which day `d` (where 0 = Sunday) appears.
- # Week 5 represents the last occurrence of day `d`, so we need to know
- # the range of the month.
- first_day, days_in_month = calendar.monthrange(year, self.m)
-
- # This equation seems magical, so I'll break it down:
- # 1. calendar says 0 = Monday, POSIX says 0 = Sunday
- # so we need first_day + 1 to get 1 = Monday -> 7 = Sunday,
- # which is still equivalent because this math is mod 7
- # 2. Get first day - desired day mod 7: -1 % 7 = 6, so we don't need
- # to do anything to adjust negative numbers.
- # 3. Add 1 because month days are a 1-based index.
- month_day = (self.d - (first_day + 1)) % 7 + 1
-
- # Now use a 0-based index version of `w` to calculate the w-th
- # occurrence of `d`
- month_day += (self.w - 1) * 7
-
- # month_day will only be > days_in_month if w was 5, and `w` means
- # "last occurrence of `d`", so now we just check if we over-shot the
- # end of the month and if so knock off 1 week.
- if month_day > days_in_month:
- month_day -= 7
-
- ordinal = self._ymd2ord(year, self.m, month_day)
- epoch = ordinal * 86400
- epoch += self.hour * 3600 + self.minute * 60 + self.second
- return epoch
-
-
-def _parse_tz_str(tz_str):
- # The tz string has the format:
- #
- # std[offset[dst[offset],start[/time],end[/time]]]
- #
- # std and dst must be 3 or more characters long and must not contain
- # a leading colon, embedded digits, commas, nor a plus or minus signs;
- # The spaces between "std" and "offset" are only for display and are
- # not actually present in the string.
- #
- # The format of the offset is ``[+|-]hh[:mm[:ss]]``
-
- offset_str, *start_end_str = tz_str.split(",", 1)
-
- # fmt: off
- parser_re = re.compile(
- r"(?P
[^<0-9:.+-]+|<[a-zA-Z0-9+\-]+>)" +
- r"((?P[+-]?\d{1,2}(:\d{2}(:\d{2})?)?)" +
- r"((?P[^0-9:.+-]+|<[a-zA-Z0-9+\-]+>)" +
- r"((?P[+-]?\d{1,2}(:\d{2}(:\d{2})?)?))?" +
- r")?" + # dst
- r")?$" # stdoff
- )
- # fmt: on
-
- m = parser_re.match(offset_str)
-
- if m is None:
- raise ValueError(f"{tz_str} is not a valid TZ string")
-
- std_abbr = m.group("std")
- dst_abbr = m.group("dst")
- dst_offset = None
-
- std_abbr = std_abbr.strip("<>")
-
- if dst_abbr:
- dst_abbr = dst_abbr.strip("<>")
-
- std_offset = m.group("stdoff")
- if std_offset:
- try:
- std_offset = _parse_tz_delta(std_offset)
- except ValueError as e:
- raise ValueError(f"Invalid STD offset in {tz_str}") from e
- else:
- std_offset = 0
-
- if dst_abbr is not None:
- dst_offset = m.group("dstoff")
- if dst_offset:
- try:
- dst_offset = _parse_tz_delta(dst_offset)
- except ValueError as e:
- raise ValueError(f"Invalid DST offset in {tz_str}") from e
- else:
- dst_offset = std_offset + 3600
-
- if not start_end_str:
- raise ValueError(f"Missing transition rules: {tz_str}")
-
- start_end_strs = start_end_str[0].split(",", 1)
- try:
- start, end = (_parse_dst_start_end(x) for x in start_end_strs)
- except ValueError as e:
- raise ValueError(f"Invalid TZ string: {tz_str}") from e
-
- return _TZStr(std_abbr, std_offset, dst_abbr, dst_offset, start, end)
- elif start_end_str:
- raise ValueError(f"Transition rule present without DST: {tz_str}")
- else:
- # This is a static ttinfo, don't return _TZStr
- return _ttinfo(
- _load_timedelta(std_offset), _load_timedelta(0), std_abbr
- )
-
-
-def _parse_dst_start_end(dststr):
- date, *time = dststr.split("/")
- if date[0] == "M":
- n_is_julian = False
- m = re.match(r"M(\d{1,2})\.(\d).(\d)$", date)
- if m is None:
- raise ValueError(f"Invalid dst start/end date: {dststr}")
- date_offset = tuple(map(int, m.groups()))
- offset = _CalendarOffset(*date_offset)
- else:
- if date[0] == "J":
- n_is_julian = True
- date = date[1:]
- else:
- n_is_julian = False
-
- doy = int(date)
- offset = _DayOffset(doy, n_is_julian)
-
- if time:
- time_components = list(map(int, time[0].split(":")))
- n_components = len(time_components)
- if n_components < 3:
- time_components.extend([0] * (3 - n_components))
- offset.hour, offset.minute, offset.second = time_components
-
- return offset
-
-
-def _parse_tz_delta(tz_delta):
- match = re.match(
- r"(?P[+-])?(?P\d{1,2})(:(?P\d{2})(:(?P\d{2}))?)?",
- tz_delta,
- )
- # Anything passed to this function should already have hit an equivalent
- # regular expression to find the section to parse.
- assert match is not None, tz_delta
-
- h, m, s = (
- int(v) if v is not None else 0
- for v in map(match.group, ("h", "m", "s"))
- )
-
- total = h * 3600 + m * 60 + s
-
- if not -86400 < total < 86400:
- raise ValueError(
- "Offset must be strictly between -24h and +24h:" + tz_delta
- )
-
- # Yes, +5 maps to an offset of -5h
- if match.group("sign") != "-":
- total *= -1
-
- return total
diff --git a/lib/backports/zoneinfo/py.typed b/lib/backports/zoneinfo/py.typed
deleted file mode 100644
index e69de29b..00000000
diff --git a/lib/bleach/__init__.py b/lib/bleach/__init__.py
index 12e93b4d..942987d9 100644
--- a/lib/bleach/__init__.py
+++ b/lib/bleach/__init__.py
@@ -11,9 +11,9 @@ from bleach.sanitizer import (
# yyyymmdd
-__releasedate__ = "20231006"
+__releasedate__ = "20241029"
# x.y.z or x.y.z.dev0 -- semver
-__version__ = "6.1.0"
+__version__ = "6.2.0"
__all__ = ["clean", "linkify"]
diff --git a/lib/bleach/_vendor/html5lib/_inputstream.py b/lib/bleach/_vendor/html5lib/_inputstream.py
index 0207dd21..09762517 100644
--- a/lib/bleach/_vendor/html5lib/_inputstream.py
+++ b/lib/bleach/_vendor/html5lib/_inputstream.py
@@ -1,7 +1,7 @@
from __future__ import absolute_import, division, unicode_literals
-from six import text_type
-from six.moves import http_client, urllib
+from bleach.six_shim import text_type
+from bleach.six_shim import http_client, urllib
import codecs
import re
diff --git a/lib/bleach/_vendor/html5lib/_tokenizer.py b/lib/bleach/_vendor/html5lib/_tokenizer.py
index 4748a197..d8848016 100644
--- a/lib/bleach/_vendor/html5lib/_tokenizer.py
+++ b/lib/bleach/_vendor/html5lib/_tokenizer.py
@@ -1,6 +1,6 @@
from __future__ import absolute_import, division, unicode_literals
-from six import unichr as chr
+from bleach.six_shim import unichr as chr
from collections import deque, OrderedDict
from sys import version_info
diff --git a/lib/bleach/_vendor/html5lib/_trie/py.py b/lib/bleach/_vendor/html5lib/_trie/py.py
index c2ba3da7..56f66bd5 100644
--- a/lib/bleach/_vendor/html5lib/_trie/py.py
+++ b/lib/bleach/_vendor/html5lib/_trie/py.py
@@ -1,5 +1,5 @@
from __future__ import absolute_import, division, unicode_literals
-from six import text_type
+from bleach.six_shim import text_type
from bisect import bisect_left
diff --git a/lib/bleach/_vendor/html5lib/_utils.py b/lib/bleach/_vendor/html5lib/_utils.py
index 9ea57942..635bb024 100644
--- a/lib/bleach/_vendor/html5lib/_utils.py
+++ b/lib/bleach/_vendor/html5lib/_utils.py
@@ -7,7 +7,7 @@ try:
except ImportError:
from collections import Mapping
-from six import text_type, PY3
+from bleach.six_shim import text_type, PY3
if PY3:
import xml.etree.ElementTree as default_etree
diff --git a/lib/bleach/_vendor/html5lib/filters/lint.py b/lib/bleach/_vendor/html5lib/filters/lint.py
index acd4d7a2..1340d972 100644
--- a/lib/bleach/_vendor/html5lib/filters/lint.py
+++ b/lib/bleach/_vendor/html5lib/filters/lint.py
@@ -1,6 +1,6 @@
from __future__ import absolute_import, division, unicode_literals
-from six import text_type
+from bleach.six_shim import text_type
from . import base
from ..constants import namespaces, voidElements
diff --git a/lib/bleach/_vendor/html5lib/filters/sanitizer.py b/lib/bleach/_vendor/html5lib/filters/sanitizer.py
index 70ef9066..5c31e974 100644
--- a/lib/bleach/_vendor/html5lib/filters/sanitizer.py
+++ b/lib/bleach/_vendor/html5lib/filters/sanitizer.py
@@ -12,7 +12,7 @@ import re
import warnings
from xml.sax.saxutils import escape, unescape
-from six.moves import urllib_parse as urlparse
+from bleach.six_shim import urllib_parse as urlparse
from . import base
from ..constants import namespaces, prefixes
diff --git a/lib/bleach/_vendor/html5lib/html5parser.py b/lib/bleach/_vendor/html5lib/html5parser.py
index 74d829d9..5427b7dd 100644
--- a/lib/bleach/_vendor/html5lib/html5parser.py
+++ b/lib/bleach/_vendor/html5lib/html5parser.py
@@ -1,5 +1,5 @@
from __future__ import absolute_import, division, unicode_literals
-from six import with_metaclass, viewkeys
+from bleach.six_shim import viewkeys
import types
@@ -423,7 +423,7 @@ def getPhases(debug):
return type
# pylint:disable=unused-argument
- class Phase(with_metaclass(getMetaclass(debug, log))):
+ class Phase(metaclass=getMetaclass(debug, log)):
"""Base class for helper object that implements each phase of processing
"""
__slots__ = ("parser", "tree", "__startTagCache", "__endTagCache")
diff --git a/lib/bleach/_vendor/html5lib/serializer.py b/lib/bleach/_vendor/html5lib/serializer.py
index c66df683..5666f49a 100644
--- a/lib/bleach/_vendor/html5lib/serializer.py
+++ b/lib/bleach/_vendor/html5lib/serializer.py
@@ -1,5 +1,5 @@
from __future__ import absolute_import, division, unicode_literals
-from six import text_type
+from bleach.six_shim import text_type
import re
diff --git a/lib/bleach/_vendor/html5lib/treebuilders/base.py b/lib/bleach/_vendor/html5lib/treebuilders/base.py
index e4a3d710..2869da00 100644
--- a/lib/bleach/_vendor/html5lib/treebuilders/base.py
+++ b/lib/bleach/_vendor/html5lib/treebuilders/base.py
@@ -1,5 +1,5 @@
from __future__ import absolute_import, division, unicode_literals
-from six import text_type
+from bleach.six_shim import text_type
from ..constants import scopingElements, tableInsertModeElements, namespaces
diff --git a/lib/bleach/_vendor/html5lib/treebuilders/etree.py b/lib/bleach/_vendor/html5lib/treebuilders/etree.py
index 086bed4e..5ccfc4d6 100644
--- a/lib/bleach/_vendor/html5lib/treebuilders/etree.py
+++ b/lib/bleach/_vendor/html5lib/treebuilders/etree.py
@@ -1,7 +1,7 @@
from __future__ import absolute_import, division, unicode_literals
# pylint:disable=protected-access
-from six import text_type
+from bleach.six_shim import text_type
import re
diff --git a/lib/bleach/_vendor/html5lib/treebuilders/etree_lxml.py b/lib/bleach/_vendor/html5lib/treebuilders/etree_lxml.py
index e73de61a..f4622322 100644
--- a/lib/bleach/_vendor/html5lib/treebuilders/etree_lxml.py
+++ b/lib/bleach/_vendor/html5lib/treebuilders/etree_lxml.py
@@ -28,7 +28,7 @@ from . import etree as etree_builders
from .. import _ihatexml
import lxml.etree as etree
-from six import PY3, binary_type
+from bleach.six_shim import PY3, binary_type
fullTree = True
diff --git a/lib/bleach/_vendor/html5lib/treewalkers/etree.py b/lib/bleach/_vendor/html5lib/treewalkers/etree.py
index 44653372..a9d9450c 100644
--- a/lib/bleach/_vendor/html5lib/treewalkers/etree.py
+++ b/lib/bleach/_vendor/html5lib/treewalkers/etree.py
@@ -3,7 +3,7 @@ from __future__ import absolute_import, division, unicode_literals
from collections import OrderedDict
import re
-from six import string_types
+from bleach.six_shim import string_types
from . import base
from .._utils import moduleFactoryFactory
diff --git a/lib/bleach/_vendor/html5lib/treewalkers/etree_lxml.py b/lib/bleach/_vendor/html5lib/treewalkers/etree_lxml.py
index a614ac5b..ef42163b 100644
--- a/lib/bleach/_vendor/html5lib/treewalkers/etree_lxml.py
+++ b/lib/bleach/_vendor/html5lib/treewalkers/etree_lxml.py
@@ -1,5 +1,5 @@
from __future__ import absolute_import, division, unicode_literals
-from six import text_type
+from bleach.six_shim import text_type
from collections import OrderedDict
diff --git a/lib/bleach/_vendor/vendor_install.sh b/lib/bleach/_vendor/vendor_install.sh
index 6e61c348..6c896ee4 100644
--- a/lib/bleach/_vendor/vendor_install.sh
+++ b/lib/bleach/_vendor/vendor_install.sh
@@ -7,8 +7,12 @@ set -o pipefail
BLEACH_VENDOR_DIR=${BLEACH_VENDOR_DIR:-"."}
DEST=${DEST:-"."}
+# Install with no dependencies
pip install --no-binary all --no-compile --no-deps -r "${BLEACH_VENDOR_DIR}/vendor.txt" --target "${DEST}"
+# Apply patches
+(cd "${DEST}" && patch -p2 < 01_html5lib_six.patch)
+
# install Python 3.6.14 urllib.urlparse for #536
curl --proto '=https' --tlsv1.2 -o "${DEST}/parse.py" https://raw.githubusercontent.com/python/cpython/v3.6.14/Lib/urllib/parse.py
(cd "${DEST}" && sha256sum parse.py > parse.py.SHA256SUM)
diff --git a/lib/bleach/html5lib_shim.py b/lib/bleach/html5lib_shim.py
index ca1cc8c8..f083db75 100644
--- a/lib/bleach/html5lib_shim.py
+++ b/lib/bleach/html5lib_shim.py
@@ -396,16 +396,25 @@ class BleachHTMLTokenizer(HTMLTokenizer):
# name that abruptly ends, but we should treat that like
# character data
yield {"type": TAG_TOKEN_TYPE_CHARACTERS, "data": self.stream.get_tag()}
+
elif last_error_token["data"] in (
+ "duplicate-attribute",
"eof-in-attribute-name",
"eof-in-attribute-value-no-quotes",
+ "expected-end-of-tag-but-got-eof",
):
# Handle the case where the text being parsed ends with <
- # followed by a series of characters and then space and then
- # more characters. It's treated as a tag name followed by an
+ # followed by characters and then space and then:
+ #
+ # * more characters
+ # * more characters repeated with a space between (e.g. "abc abc")
+ # * more characters and then a space and then an EOF (e.g. "abc def ")
+ #
+ # These cases are treated as a tag name followed by an
# attribute that abruptly ends, but we should treat that like
- # character data.
+ # character data instead.
yield {"type": TAG_TOKEN_TYPE_CHARACTERS, "data": self.stream.get_tag()}
+
else:
yield last_error_token
diff --git a/lib/bleach/six_shim.py b/lib/bleach/six_shim.py
new file mode 100644
index 00000000..7db96011
--- /dev/null
+++ b/lib/bleach/six_shim.py
@@ -0,0 +1,19 @@
+"""
+Replacement module for what html5lib uses six for.
+"""
+
+import http.client
+import operator
+import urllib
+
+
+PY3 = True
+binary_type = bytes
+string_types = (str,)
+text_type = str
+unichr = chr
+viewkeys = operator.methodcaller("keys")
+
+http_client = http.client
+urllib = urllib
+urllib_parse = urllib.parse
diff --git a/lib/certifi/__init__.py b/lib/certifi/__init__.py
index d321f1bc..f61d77fa 100644
--- a/lib/certifi/__init__.py
+++ b/lib/certifi/__init__.py
@@ -1,4 +1,4 @@
from .core import contents, where
__all__ = ["contents", "where"]
-__version__ = "2024.07.04"
+__version__ = "2024.08.30"
diff --git a/lib/certifi/cacert.pem b/lib/certifi/cacert.pem
index a6581589..3c165a1b 100644
--- a/lib/certifi/cacert.pem
+++ b/lib/certifi/cacert.pem
@@ -4796,3 +4796,134 @@ PQQDAwNoADBlAjAdfKR7w4l1M+E7qUW/Runpod3JIha3RxEL2Jq68cgLcFBTApFw
hVmpHqTm6iMxoAACMQD94vizrxa5HnPEluPBMBnYfubDl94cT7iJLzPrSA8Z94dG
XSaQpYXFuXqUPoeovQA=
-----END CERTIFICATE-----
+
+# Issuer: CN=TWCA CYBER Root CA O=TAIWAN-CA OU=Root CA
+# Subject: CN=TWCA CYBER Root CA O=TAIWAN-CA OU=Root CA
+# Label: "TWCA CYBER Root CA"
+# Serial: 85076849864375384482682434040119489222
+# MD5 Fingerprint: 0b:33:a0:97:52:95:d4:a9:fd:bb:db:6e:a3:55:5b:51
+# SHA1 Fingerprint: f6:b1:1c:1a:83:38:e9:7b:db:b3:a8:c8:33:24:e0:2d:9c:7f:26:66
+# SHA256 Fingerprint: 3f:63:bb:28:14:be:17:4e:c8:b6:43:9c:f0:8d:6d:56:f0:b7:c4:05:88:3a:56:48:a3:34:42:4d:6b:3e:c5:58
+-----BEGIN CERTIFICATE-----
+MIIFjTCCA3WgAwIBAgIQQAE0jMIAAAAAAAAAATzyxjANBgkqhkiG9w0BAQwFADBQ
+MQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290
+IENBMRswGQYDVQQDExJUV0NBIENZQkVSIFJvb3QgQ0EwHhcNMjIxMTIyMDY1NDI5
+WhcNNDcxMTIyMTU1OTU5WjBQMQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FO
+LUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NBIENZQkVSIFJvb3Qg
+Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDG+Moe2Qkgfh1sTs6P
+40czRJzHyWmqOlt47nDSkvgEs1JSHWdyKKHfi12VCv7qze33Kc7wb3+szT3vsxxF
+avcokPFhV8UMxKNQXd7UtcsZyoC5dc4pztKFIuwCY8xEMCDa6pFbVuYdHNWdZsc/
+34bKS1PE2Y2yHer43CdTo0fhYcx9tbD47nORxc5zb87uEB8aBs/pJ2DFTxnk684i
+JkXXYJndzk834H/nY62wuFm40AZoNWDTNq5xQwTxaWV4fPMf88oon1oglWa0zbfu
+j3ikRRjpJi+NmykosaS3Om251Bw4ckVYsV7r8Cibt4LK/c/WMw+f+5eesRycnupf
+Xtuq3VTpMCEobY5583WSjCb+3MX2w7DfRFlDo7YDKPYIMKoNM+HvnKkHIuNZW0CP
+2oi3aQiotyMuRAlZN1vH4xfyIutuOVLF3lSnmMlLIJXcRolftBL5hSmO68gnFSDA
+S9TMfAxsNAwmmyYxpjyn9tnQS6Jk/zuZQXLB4HCX8SS7K8R0IrGsayIyJNN4KsDA
+oS/xUgXJP+92ZuJF2A09rZXIx4kmyA+upwMu+8Ff+iDhcK2wZSA3M2Cw1a/XDBzC
+kHDXShi8fgGwsOsVHkQGzaRP6AzRwyAQ4VRlnrZR0Bp2a0JaWHY06rc3Ga4udfmW
+5cFZ95RXKSWNOkyrTZpB0F8mAwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSdhWEUfMFib5do5E83QOGt4A1WNzAd
+BgNVHQ4EFgQUnYVhFHzBYm+XaORPN0DhreANVjcwDQYJKoZIhvcNAQEMBQADggIB
+AGSPesRiDrWIzLjHhg6hShbNcAu3p4ULs3a2D6f/CIsLJc+o1IN1KriWiLb73y0t
+tGlTITVX1olNc79pj3CjYcya2x6a4CD4bLubIp1dhDGaLIrdaqHXKGnK/nZVekZn
+68xDiBaiA9a5F/gZbG0jAn/xX9AKKSM70aoK7akXJlQKTcKlTfjF/biBzysseKNn
+TKkHmvPfXvt89YnNdJdhEGoHK4Fa0o635yDRIG4kqIQnoVesqlVYL9zZyvpoBJ7t
+RCT5dEA7IzOrg1oYJkK2bVS1FmAwbLGg+LhBoF1JSdJlBTrq/p1hvIbZv97Tujqx
+f36SNI7JAG7cmL3c7IAFrQI932XtCwP39xaEBDG6k5TY8hL4iuO/Qq+n1M0RFxbI
+Qh0UqEL20kCGoE8jypZFVmAGzbdVAaYBlGX+bgUJurSkquLvWL69J1bY73NxW0Qz
+8ppy6rBePm6pUlvscG21h483XjyMnM7k8M4MZ0HMzvaAq07MTFb1wWFZk7Q+ptq4
+NxKfKjLji7gh7MMrZQzvIt6IKTtM1/r+t+FHvpw+PoP7UV31aPcuIYXcv/Fa4nzX
+xeSDwWrruoBa3lwtcHb4yOWHh8qgnaHlIhInD0Q9HWzq1MKLL295q39QpsQZp6F6
+t5b5wR9iWqJDB0BeJsas7a5wFsWqynKKTbDPAYsDP27X
+-----END CERTIFICATE-----
+
+# Issuer: CN=SecureSign Root CA12 O=Cybertrust Japan Co., Ltd.
+# Subject: CN=SecureSign Root CA12 O=Cybertrust Japan Co., Ltd.
+# Label: "SecureSign Root CA12"
+# Serial: 587887345431707215246142177076162061960426065942
+# MD5 Fingerprint: c6:89:ca:64:42:9b:62:08:49:0b:1e:7f:e9:07:3d:e8
+# SHA1 Fingerprint: 7a:22:1e:3d:de:1b:06:ac:9e:c8:47:70:16:8e:3c:e5:f7:6b:06:f4
+# SHA256 Fingerprint: 3f:03:4b:b5:70:4d:44:b2:d0:85:45:a0:20:57:de:93:eb:f3:90:5f:ce:72:1a:cb:c7:30:c0:6d:da:ee:90:4e
+-----BEGIN CERTIFICATE-----
+MIIDcjCCAlqgAwIBAgIUZvnHwa/swlG07VOX5uaCwysckBYwDQYJKoZIhvcNAQEL
+BQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28u
+LCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExMjAeFw0yMDA0MDgw
+NTM2NDZaFw00MDA0MDgwNTM2NDZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpD
+eWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBS
+b290IENBMTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6OcE3emhF
+KxS06+QT61d1I02PJC0W6K6OyX2kVzsqdiUzg2zqMoqUm048luT9Ub+ZyZN+v/mt
+p7JIKwccJ/VMvHASd6SFVLX9kHrko+RRWAPNEHl57muTH2SOa2SroxPjcf59q5zd
+J1M3s6oYwlkm7Fsf0uZlfO+TvdhYXAvA42VvPMfKWeP+bl+sg779XSVOKik71gur
+FzJ4pOE+lEa+Ym6b3kaosRbnhW70CEBFEaCeVESE99g2zvVQR9wsMJvuwPWW0v4J
+hscGWa5Pro4RmHvzC1KqYiaqId+OJTN5lxZJjfU+1UefNzFJM3IFTQy2VYzxV4+K
+h9GtxRESOaCtAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
+AgEGMB0GA1UdDgQWBBRXNPN0zwRL1SXm8UC2LEzZLemgrTANBgkqhkiG9w0BAQsF
+AAOCAQEAPrvbFxbS8hQBICw4g0utvsqFepq2m2um4fylOqyttCg6r9cBg0krY6Ld
+mmQOmFxv3Y67ilQiLUoT865AQ9tPkbeGGuwAtEGBpE/6aouIs3YIcipJQMPTw4WJ
+mBClnW8Zt7vPemVV2zfrPIpyMpcemik+rY3moxtt9XUa5rBouVui7mlHJzWhhpmA
+8zNL4WukJsPvdFlseqJkth5Ew1DgDzk9qTPxpfPSvWKErI4cqc1avTc7bgoitPQV
+55FYxTpE05Uo2cBl6XLK0A+9H7MV2anjpEcJnuDLN/v9vZfVvhgaaaI5gdka9at/
+yOPiZwud9AzqVN/Ssq+xIvEg37xEHA==
+-----END CERTIFICATE-----
+
+# Issuer: CN=SecureSign Root CA14 O=Cybertrust Japan Co., Ltd.
+# Subject: CN=SecureSign Root CA14 O=Cybertrust Japan Co., Ltd.
+# Label: "SecureSign Root CA14"
+# Serial: 575790784512929437950770173562378038616896959179
+# MD5 Fingerprint: 71:0d:72:fa:92:19:65:5e:89:04:ac:16:33:f0:bc:d5
+# SHA1 Fingerprint: dd:50:c0:f7:79:b3:64:2e:74:a2:b8:9d:9f:d3:40:dd:bb:f0:f2:4f
+# SHA256 Fingerprint: 4b:00:9c:10:34:49:4f:9a:b5:6b:ba:3b:a1:d6:27:31:fc:4d:20:d8:95:5a:dc:ec:10:a9:25:60:72:61:e3:38
+-----BEGIN CERTIFICATE-----
+MIIFcjCCA1qgAwIBAgIUZNtaDCBO6Ncpd8hQJ6JaJ90t8sswDQYJKoZIhvcNAQEM
+BQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28u
+LCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNDAeFw0yMDA0MDgw
+NzA2MTlaFw00NTA0MDgwNzA2MTlaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpD
+eWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBS
+b290IENBMTQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDF0nqh1oq/
+FjHQmNE6lPxauG4iwWL3pwon71D2LrGeaBLwbCRjOfHw3xDG3rdSINVSW0KZnvOg
+vlIfX8xnbacuUKLBl422+JX1sLrcneC+y9/3OPJH9aaakpUqYllQC6KxNedlsmGy
+6pJxaeQp8E+BgQQ8sqVb1MWoWWd7VRxJq3qdwudzTe/NCcLEVxLbAQ4jeQkHO6Lo
+/IrPj8BGJJw4J+CDnRugv3gVEOuGTgpa/d/aLIJ+7sr2KeH6caH3iGicnPCNvg9J
+kdjqOvn90Ghx2+m1K06Ckm9mH+Dw3EzsytHqunQG+bOEkJTRX45zGRBdAuVwpcAQ
+0BB8b8VYSbSwbprafZX1zNoCr7gsfXmPvkPx+SgojQlD+Ajda8iLLCSxjVIHvXib
+y8posqTdDEx5YMaZ0ZPxMBoH064iwurO8YQJzOAUbn8/ftKChazcqRZOhaBgy/ac
+18izju3Gm5h1DVXoX+WViwKkrkMpKBGk5hIwAUt1ax5mnXkvpXYvHUC0bcl9eQjs
+0Wq2XSqypWa9a4X0dFbD9ed1Uigspf9mR6XU/v6eVL9lfgHWMI+lNpyiUBzuOIAB
+SMbHdPTGrMNASRZhdCyvjG817XsYAFs2PJxQDcqSMxDxJklt33UkN4Ii1+iW/RVL
+ApY+B3KVfqs9TC7XyvDf4Fg/LS8EmjijAQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUBpOjCl4oaTeqYR3r6/wtbyPk
+86AwDQYJKoZIhvcNAQEMBQADggIBAJaAcgkGfpzMkwQWu6A6jZJOtxEaCnFxEM0E
+rX+lRVAQZk5KQaID2RFPeje5S+LGjzJmdSX7684/AykmjbgWHfYfM25I5uj4V7Ib
+ed87hwriZLoAymzvftAj63iP/2SbNDefNWWipAA9EiOWWF3KY4fGoweITedpdopT
+zfFP7ELyk+OZpDc8h7hi2/DsHzc/N19DzFGdtfCXwreFamgLRB7lUe6TzktuhsHS
+DCRZNhqfLJGP4xjblJUK7ZGqDpncllPjYYPGFrojutzdfhrGe0K22VoF3Jpf1d+4
+2kd92jjbrDnVHmtsKheMYc2xbXIBw8MgAGJoFjHVdqqGuw6qnsb58Nn4DSEC5MUo
+FlkRudlpcyqSeLiSV5sI8jrlL5WwWLdrIBRtFO8KvH7YVdiI2i/6GaX7i+B/OfVy
+K4XELKzvGUWSTLNhB9xNH27SgRNcmvMSZ4PPmz+Ln52kuaiWA3rF7iDeM9ovnhp6
+dB7h7sxaOgTdsxoEqBRjrLdHEoOabPXm6RUVkRqEGQ6UROcSjiVbgGcZ3GOTEAtl
+Lor6CZpO2oYofaphNdgOpygau1LgePhsumywbrmHXumZNTfxPWQrqaA0k89jL9WB
+365jJ6UeTo3cKXhZ+PmhIIynJkBugnLNeLLIjzwec+fBH7/PzqUqm9tEZDKgu39c
+JRNItX+S
+-----END CERTIFICATE-----
+
+# Issuer: CN=SecureSign Root CA15 O=Cybertrust Japan Co., Ltd.
+# Subject: CN=SecureSign Root CA15 O=Cybertrust Japan Co., Ltd.
+# Label: "SecureSign Root CA15"
+# Serial: 126083514594751269499665114766174399806381178503
+# MD5 Fingerprint: 13:30:fc:c4:62:a6:a9:de:b5:c1:68:af:b5:d2:31:47
+# SHA1 Fingerprint: cb:ba:83:c8:c1:5a:5d:f1:f9:73:6f:ca:d7:ef:28:13:06:4a:07:7d
+# SHA256 Fingerprint: e7:78:f0:f0:95:fe:84:37:29:cd:1a:00:82:17:9e:53:14:a9:c2:91:44:28:05:e1:fb:1d:8f:b6:b8:88:6c:3a
+-----BEGIN CERTIFICATE-----
+MIICIzCCAamgAwIBAgIUFhXHw9hJp75pDIqI7fBw+d23PocwCgYIKoZIzj0EAwMw
+UTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBM
+dGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNTAeFw0yMDA0MDgwODMy
+NTZaFw00NTA0MDgwODMyNTZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpDeWJl
+cnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBSb290
+IENBMTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQLUHSNZDKZmbPSYAi4Io5GdCx4
+wCtELW1fHcmuS1Iggz24FG1Th2CeX2yF2wYUleDHKP+dX+Sq8bOLbe1PL0vJSpSR
+ZHX+AezB2Ot6lHhWGENfa4HL9rzatAy2KZMIaY+jQjBAMA8GA1UdEwEB/wQFMAMB
+Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTrQciu/NWeUUj1vYv0hyCTQSvT
+9DAKBggqhkjOPQQDAwNoADBlAjEA2S6Jfl5OpBEHvVnCB96rMjhTKkZEBhd6zlHp
+4P9mLQlO4E/0BdGF9jVg3PVys0Z9AjBEmEYagoUeYWmJSwdLZrWeqrqgHkHZAXQ6
+bkU6iYAZezKYVWOr62Nuk22rGwlgMU4=
+-----END CERTIFICATE-----
diff --git a/lib/charset_normalizer/api.py b/lib/charset_normalizer/api.py
index 0ba08e3a..e3f2283b 100644
--- a/lib/charset_normalizer/api.py
+++ b/lib/charset_normalizer/api.py
@@ -159,6 +159,8 @@ def from_bytes(
results: CharsetMatches = CharsetMatches()
+ early_stop_results: CharsetMatches = CharsetMatches()
+
sig_encoding, sig_payload = identify_sig_or_bom(sequences)
if sig_encoding is not None:
@@ -221,16 +223,20 @@ def from_bytes(
try:
if is_too_large_sequence and is_multi_byte_decoder is False:
str(
- sequences[: int(50e4)]
- if strip_sig_or_bom is False
- else sequences[len(sig_payload) : int(50e4)],
+ (
+ sequences[: int(50e4)]
+ if strip_sig_or_bom is False
+ else sequences[len(sig_payload) : int(50e4)]
+ ),
encoding=encoding_iana,
)
else:
decoded_payload = str(
- sequences
- if strip_sig_or_bom is False
- else sequences[len(sig_payload) :],
+ (
+ sequences
+ if strip_sig_or_bom is False
+ else sequences[len(sig_payload) :]
+ ),
encoding=encoding_iana,
)
except (UnicodeDecodeError, LookupError) as e:
@@ -367,7 +373,13 @@ def from_bytes(
and not lazy_str_hard_failure
):
fallback_entry = CharsetMatch(
- sequences, encoding_iana, threshold, False, [], decoded_payload
+ sequences,
+ encoding_iana,
+ threshold,
+ False,
+ [],
+ decoded_payload,
+ preemptive_declaration=specified_encoding,
)
if encoding_iana == specified_encoding:
fallback_specified = fallback_entry
@@ -421,28 +433,58 @@ def from_bytes(
),
)
- results.append(
- CharsetMatch(
- sequences,
- encoding_iana,
- mean_mess_ratio,
- bom_or_sig_available,
- cd_ratios_merged,
- decoded_payload,
- )
+ current_match = CharsetMatch(
+ sequences,
+ encoding_iana,
+ mean_mess_ratio,
+ bom_or_sig_available,
+ cd_ratios_merged,
+ (
+ decoded_payload
+ if (
+ is_too_large_sequence is False
+ or encoding_iana in [specified_encoding, "ascii", "utf_8"]
+ )
+ else None
+ ),
+ preemptive_declaration=specified_encoding,
)
+ results.append(current_match)
+
if (
encoding_iana in [specified_encoding, "ascii", "utf_8"]
and mean_mess_ratio < 0.1
):
+ # If md says nothing to worry about, then... stop immediately!
+ if mean_mess_ratio == 0.0:
+ logger.debug(
+ "Encoding detection: %s is most likely the one.",
+ current_match.encoding,
+ )
+ if explain:
+ logger.removeHandler(explain_handler)
+ logger.setLevel(previous_logger_level)
+ return CharsetMatches([current_match])
+
+ early_stop_results.append(current_match)
+
+ if (
+ len(early_stop_results)
+ and (specified_encoding is None or specified_encoding in tested)
+ and "ascii" in tested
+ and "utf_8" in tested
+ ):
+ probable_result: CharsetMatch = early_stop_results.best() # type: ignore[assignment]
logger.debug(
- "Encoding detection: %s is most likely the one.", encoding_iana
+ "Encoding detection: %s is most likely the one.",
+ probable_result.encoding,
)
if explain:
logger.removeHandler(explain_handler)
logger.setLevel(previous_logger_level)
- return CharsetMatches([results[encoding_iana]])
+
+ return CharsetMatches([probable_result])
if encoding_iana == sig_encoding:
logger.debug(
diff --git a/lib/charset_normalizer/cli/__main__.py b/lib/charset_normalizer/cli/__main__.py
index f4bcbaac..e7edd0fc 100644
--- a/lib/charset_normalizer/cli/__main__.py
+++ b/lib/charset_normalizer/cli/__main__.py
@@ -109,6 +109,14 @@ def cli_detect(argv: Optional[List[str]] = None) -> int:
dest="force",
help="Replace file without asking if you are sure, use this flag with caution.",
)
+ parser.add_argument(
+ "-i",
+ "--no-preemptive",
+ action="store_true",
+ default=False,
+ dest="no_preemptive",
+ help="Disable looking at a charset declaration to hint the detector.",
+ )
parser.add_argument(
"-t",
"--threshold",
@@ -133,21 +141,35 @@ def cli_detect(argv: Optional[List[str]] = None) -> int:
args = parser.parse_args(argv)
if args.replace is True and args.normalize is False:
+ if args.files:
+ for my_file in args.files:
+ my_file.close()
print("Use --replace in addition of --normalize only.", file=sys.stderr)
return 1
if args.force is True and args.replace is False:
+ if args.files:
+ for my_file in args.files:
+ my_file.close()
print("Use --force in addition of --replace only.", file=sys.stderr)
return 1
if args.threshold < 0.0 or args.threshold > 1.0:
+ if args.files:
+ for my_file in args.files:
+ my_file.close()
print("--threshold VALUE should be between 0. AND 1.", file=sys.stderr)
return 1
x_ = []
for my_file in args.files:
- matches = from_fp(my_file, threshold=args.threshold, explain=args.verbose)
+ matches = from_fp(
+ my_file,
+ threshold=args.threshold,
+ explain=args.verbose,
+ preemptive_behaviour=args.no_preemptive is False,
+ )
best_guess = matches.best()
@@ -155,9 +177,11 @@ def cli_detect(argv: Optional[List[str]] = None) -> int:
print(
'Unable to identify originating encoding for "{}". {}'.format(
my_file.name,
- "Maybe try increasing maximum amount of chaos."
- if args.threshold < 1.0
- else "",
+ (
+ "Maybe try increasing maximum amount of chaos."
+ if args.threshold < 1.0
+ else ""
+ ),
),
file=sys.stderr,
)
@@ -258,8 +282,8 @@ def cli_detect(argv: Optional[List[str]] = None) -> int:
try:
x_[0].unicode_path = join(dir_path, ".".join(o_))
- with open(x_[0].unicode_path, "w", encoding="utf-8") as fp:
- fp.write(str(best_guess))
+ with open(x_[0].unicode_path, "wb") as fp:
+ fp.write(best_guess.output())
except IOError as e:
print(str(e), file=sys.stderr)
if my_file.closed is False:
diff --git a/lib/charset_normalizer/constant.py b/lib/charset_normalizer/constant.py
index 86349046..f8f2a811 100644
--- a/lib/charset_normalizer/constant.py
+++ b/lib/charset_normalizer/constant.py
@@ -544,6 +544,8 @@ COMMON_SAFE_ASCII_CHARACTERS: Set[str] = {
"|",
'"',
"-",
+ "(",
+ ")",
}
diff --git a/lib/charset_normalizer/legacy.py b/lib/charset_normalizer/legacy.py
index 43aad21a..3f6d4907 100644
--- a/lib/charset_normalizer/legacy.py
+++ b/lib/charset_normalizer/legacy.py
@@ -1,13 +1,24 @@
-from typing import Any, Dict, Optional, Union
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any, Optional
from warnings import warn
from .api import from_bytes
from .constant import CHARDET_CORRESPONDENCE
+# TODO: remove this check when dropping Python 3.7 support
+if TYPE_CHECKING:
+ from typing_extensions import TypedDict
+
+ class ResultDict(TypedDict):
+ encoding: Optional[str]
+ language: str
+ confidence: Optional[float]
+
def detect(
byte_str: bytes, should_rename_legacy: bool = False, **kwargs: Any
-) -> Dict[str, Optional[Union[str, float]]]:
+) -> ResultDict:
"""
chardet legacy method
Detect the encoding of the given byte string. It should be mostly backward-compatible.
diff --git a/lib/charset_normalizer/md.py b/lib/charset_normalizer/md.py
index 77897aae..d834db0e 100644
--- a/lib/charset_normalizer/md.py
+++ b/lib/charset_normalizer/md.py
@@ -236,7 +236,7 @@ class SuspiciousRange(MessDetectorPlugin):
@property
def ratio(self) -> float:
- if self._character_count <= 24:
+ if self._character_count <= 13:
return 0.0
ratio_of_suspicious_range_usage: float = (
@@ -260,6 +260,7 @@ class SuperWeirdWordPlugin(MessDetectorPlugin):
self._buffer: str = ""
self._buffer_accent_count: int = 0
+ self._buffer_glyph_count: int = 0
def eligible(self, character: str) -> bool:
return True
@@ -279,6 +280,14 @@ class SuperWeirdWordPlugin(MessDetectorPlugin):
and is_thai(character) is False
):
self._foreign_long_watch = True
+ if (
+ is_cjk(character)
+ or is_hangul(character)
+ or is_katakana(character)
+ or is_hiragana(character)
+ or is_thai(character)
+ ):
+ self._buffer_glyph_count += 1
return
if not self._buffer:
return
@@ -291,17 +300,20 @@ class SuperWeirdWordPlugin(MessDetectorPlugin):
self._character_count += buffer_length
if buffer_length >= 4:
- if self._buffer_accent_count / buffer_length > 0.34:
+ if self._buffer_accent_count / buffer_length >= 0.5:
self._is_current_word_bad = True
# Word/Buffer ending with an upper case accentuated letter are so rare,
# that we will consider them all as suspicious. Same weight as foreign_long suspicious.
- if (
+ elif (
is_accentuated(self._buffer[-1])
and self._buffer[-1].isupper()
and all(_.isupper() for _ in self._buffer) is False
):
self._foreign_long_count += 1
self._is_current_word_bad = True
+ elif self._buffer_glyph_count == 1:
+ self._is_current_word_bad = True
+ self._foreign_long_count += 1
if buffer_length >= 24 and self._foreign_long_watch:
camel_case_dst = [
i
@@ -325,6 +337,7 @@ class SuperWeirdWordPlugin(MessDetectorPlugin):
self._foreign_long_watch = False
self._buffer = ""
self._buffer_accent_count = 0
+ self._buffer_glyph_count = 0
elif (
character not in {"<", ">", "-", "=", "~", "|", "_"}
and character.isdigit() is False
diff --git a/lib/charset_normalizer/models.py b/lib/charset_normalizer/models.py
index a760b9c5..6f6b86b3 100644
--- a/lib/charset_normalizer/models.py
+++ b/lib/charset_normalizer/models.py
@@ -1,9 +1,10 @@
from encodings.aliases import aliases
from hashlib import sha256
from json import dumps
+from re import sub
from typing import Any, Dict, Iterator, List, Optional, Tuple, Union
-from .constant import TOO_BIG_SEQUENCE
+from .constant import RE_POSSIBLE_ENCODING_INDICATION, TOO_BIG_SEQUENCE
from .utils import iana_name, is_multi_byte_encoding, unicode_range
@@ -16,6 +17,7 @@ class CharsetMatch:
has_sig_or_bom: bool,
languages: "CoherenceMatches",
decoded_payload: Optional[str] = None,
+ preemptive_declaration: Optional[str] = None,
):
self._payload: bytes = payload
@@ -33,13 +35,13 @@ class CharsetMatch:
self._string: Optional[str] = decoded_payload
+ self._preemptive_declaration: Optional[str] = preemptive_declaration
+
def __eq__(self, other: object) -> bool:
if not isinstance(other, CharsetMatch):
- raise TypeError(
- "__eq__ cannot be invoked on {} and {}.".format(
- str(other.__class__), str(self.__class__)
- )
- )
+ if isinstance(other, str):
+ return iana_name(other) == self.encoding
+ return False
return self.encoding == other.encoding and self.fingerprint == other.fingerprint
def __lt__(self, other: object) -> bool:
@@ -210,7 +212,24 @@ class CharsetMatch:
"""
if self._output_encoding is None or self._output_encoding != encoding:
self._output_encoding = encoding
- self._output_payload = str(self).encode(encoding, "replace")
+ decoded_string = str(self)
+ if (
+ self._preemptive_declaration is not None
+ and self._preemptive_declaration.lower()
+ not in ["utf-8", "utf8", "utf_8"]
+ ):
+ patched_header = sub(
+ RE_POSSIBLE_ENCODING_INDICATION,
+ lambda m: m.string[m.span()[0] : m.span()[1]].replace(
+ m.groups()[0], iana_name(self._output_encoding) # type: ignore[arg-type]
+ ),
+ decoded_string[:8192],
+ 1,
+ )
+
+ decoded_string = patched_header + decoded_string[8192:]
+
+ self._output_payload = decoded_string.encode(encoding, "replace")
return self._output_payload # type: ignore
@@ -266,7 +285,7 @@ class CharsetMatches:
)
)
# We should disable the submatch factoring when the input file is too heavy (conserve RAM usage)
- if len(item.raw) <= TOO_BIG_SEQUENCE:
+ if len(item.raw) < TOO_BIG_SEQUENCE:
for match in self._results:
if match.fingerprint == item.fingerprint and match.chaos == item.chaos:
match.add_submatch(item)
diff --git a/lib/charset_normalizer/version.py b/lib/charset_normalizer/version.py
index 5a4da4ff..699990ee 100644
--- a/lib/charset_normalizer/version.py
+++ b/lib/charset_normalizer/version.py
@@ -2,5 +2,5 @@
Expose version
"""
-__version__ = "3.3.2"
+__version__ = "3.4.0"
VERSION = __version__.split(".")
diff --git a/lib/cherrypy_cors/__init__.py b/lib/cherrypy_cors/__init__.py
new file mode 100644
index 00000000..54003451
--- /dev/null
+++ b/lib/cherrypy_cors/__init__.py
@@ -0,0 +1,255 @@
+import re
+
+import cherrypy
+from cherrypy.lib import set_vary_header
+import httpagentparser
+
+
+CORS_ALLOW_METHODS = 'Access-Control-Allow-Methods'
+CORS_ALLOW_ORIGIN = 'Access-Control-Allow-Origin'
+CORS_ALLOW_CREDENTIALS = 'Access-Control-Allow-Credentials'
+CORS_EXPOSE_HEADERS = 'Access-Control-Expose-Headers'
+CORS_REQUEST_METHOD = 'Access-Control-Request-Method'
+CORS_REQUEST_HEADERS = 'Access-Control-Request-Headers'
+CORS_MAX_AGE = 'Access-Control-Max-Age'
+CORS_ALLOW_HEADERS = 'Access-Control-Allow-Headers'
+PUBLIC_ORIGIN = '*'
+
+
+def expose(allow_credentials=False, expose_headers=None, origins=None):
+ """Adds CORS support to the resource.
+
+ If the resource is allowed to be exposed, the value of the
+ `Access-Control-Allow-Origin`_ header in the response will echo
+ the `Origin`_ request header, and `Origin` will be
+ appended to the `Vary`_ response header.
+
+ :param allow_credentials: Use credentials to make cookies work
+ (see `Access-Control-Allow-Credentials`_).
+ :type allow_credentials: bool
+ :param expose_headers: List of headers clients will be able to access
+ (see `Access-Control-Expose-Headers`_).
+ :type expose_headers: list or None
+ :param origins: List of allowed origins clients must reference.
+ :type origins: list or None
+
+ :returns: Whether the resource is being exposed.
+ :rtype: bool
+
+ - Configuration example:
+
+ .. code-block:: python
+
+ config = {
+ '/static': {
+ 'tools.staticdir.on': True,
+ 'cors.expose.on': True,
+ }
+ }
+ - Decorator example:
+
+ .. code-block:: python
+
+ @cherrypy_cors.tools.expose()
+ def DELETE(self):
+ self._delete()
+
+ """
+ if _get_cors().expose(allow_credentials, expose_headers, origins):
+ _safe_caching_headers()
+ return True
+ return False
+
+
+def expose_public(expose_headers=None):
+ """Adds CORS support to the resource from any origin.
+
+ If the resource is allowed to be exposed, the value of the
+ `Access-Control-Allow-Origin`_ header in the response will be `*`.
+
+ :param expose_headers: List of headers clients will be able to access
+ (see `Access-Control-Expose-Headers`_).
+ :type expose_headers: list or None
+
+ :rtype: None
+ """
+ _get_cors().expose_public(expose_headers)
+
+
+def preflight(
+ allowed_methods,
+ allowed_headers=None,
+ allow_credentials=False,
+ max_age=None,
+ origins=None,
+):
+ """Adds CORS `preflight`_ support to a `HTTP OPTIONS` request.
+
+ :param allowed_methods: List of supported `HTTP` methods
+ (see `Access-Control-Allow-Methods`_).
+ :type allowed_methods: list or None
+ :param allowed_headers: List of supported `HTTP` headers
+ (see `Access-Control-Allow-Headers`_).
+ :type allowed_headers: list or None
+ :param allow_credentials: Use credentials to make cookies work
+ (see `Access-Control-Allow-Credentials`_).
+ :type allow_credentials: bool
+ :param max_age: Seconds to cache the preflight request
+ (see `Access-Control-Max-Age`_).
+ :type max_age: int
+ :param origins: List of allowed origins clients must reference.
+ :type origins: list or None
+
+ :returns: Whether the preflight is allowed.
+ :rtype: bool
+
+ - Used as a decorator with the `Method Dispatcher`_
+
+ .. code-block:: python
+
+ @cherrypy_cors.tools.preflight(
+ allowed_methods=["GET", "DELETE", "PUT"])
+ def OPTIONS(self):
+ pass
+
+ - Function call with the `Object Dispatcher`_
+
+ .. code-block:: python
+
+ @cherrypy.expose
+ @cherrypy.tools.allow(
+ methods=["GET", "DELETE", "PUT", "OPTIONS"])
+ def thing(self):
+ if cherrypy.request.method == "OPTIONS":
+ cherrypy_cors.preflight(
+ allowed_methods=["GET", "DELETE", "PUT"])
+ else:
+ self._do_other_things()
+
+ """
+ if _get_cors().preflight(
+ allowed_methods, allowed_headers, allow_credentials, max_age, origins
+ ):
+ _safe_caching_headers()
+ return True
+ return False
+
+
+def install():
+ """Install the toolbox such that it's available in all applications."""
+ cherrypy._cptree.Application.toolboxes.update(cors=tools)
+
+
+class CORS:
+ """A generic CORS handler."""
+
+ def __init__(self, req_headers, resp_headers):
+ self.req_headers = req_headers
+ self.resp_headers = resp_headers
+
+ def expose(self, allow_credentials, expose_headers, origins):
+ if self._is_valid_origin(origins):
+ self._add_origin_and_credentials_headers(allow_credentials)
+ self._add_expose_headers(expose_headers)
+ return True
+ return False
+
+ def expose_public(self, expose_headers):
+ self._add_public_origin()
+ self._add_expose_headers(expose_headers)
+
+ def preflight(
+ self, allowed_methods, allowed_headers, allow_credentials, max_age, origins
+ ):
+ if self._is_valid_preflight_request(allowed_headers, allowed_methods, origins):
+ self._add_origin_and_credentials_headers(allow_credentials)
+ self._add_prefligt_headers(allowed_methods, max_age)
+ return True
+ return False
+
+ @property
+ def origin(self):
+ return self.req_headers.get('Origin')
+
+ def _is_valid_origin(self, origins):
+ if origins is None:
+ origins = [self.origin]
+ origins = map(self._make_regex, origins)
+ return self.origin is not None and any(
+ origin.match(self.origin) for origin in origins
+ )
+
+ @staticmethod
+ def _make_regex(pattern):
+ if isinstance(pattern, str):
+ pattern = re.compile(re.escape(pattern) + '$')
+ return pattern
+
+ def _add_origin_and_credentials_headers(self, allow_credentials):
+ self.resp_headers[CORS_ALLOW_ORIGIN] = self.origin
+ if allow_credentials:
+ self.resp_headers[CORS_ALLOW_CREDENTIALS] = 'true'
+
+ def _add_public_origin(self):
+ self.resp_headers[CORS_ALLOW_ORIGIN] = PUBLIC_ORIGIN
+
+ def _add_expose_headers(self, expose_headers):
+ if expose_headers:
+ self.resp_headers[CORS_EXPOSE_HEADERS] = expose_headers
+
+ @property
+ def requested_method(self):
+ return self.req_headers.get(CORS_REQUEST_METHOD)
+
+ @property
+ def requested_headers(self):
+ return self.req_headers.get(CORS_REQUEST_HEADERS)
+
+ def _has_valid_method(self, allowed_methods):
+ return self.requested_method and self.requested_method in allowed_methods
+
+ def _valid_headers(self, allowed_headers):
+ if self.requested_headers and allowed_headers:
+ for header in self.requested_headers.split(','):
+ if header.strip() not in allowed_headers:
+ return False
+ return True
+
+ def _is_valid_preflight_request(self, allowed_headers, allowed_methods, origins):
+ return (
+ self._is_valid_origin(origins)
+ and self._has_valid_method(allowed_methods)
+ and self._valid_headers(allowed_headers)
+ )
+
+ def _add_prefligt_headers(self, allowed_methods, max_age):
+ rh = self.resp_headers
+ rh[CORS_ALLOW_METHODS] = ', '.join(allowed_methods)
+ if max_age:
+ rh[CORS_MAX_AGE] = max_age
+ if self.requested_headers:
+ rh[CORS_ALLOW_HEADERS] = self.requested_headers
+
+
+def _get_cors():
+ return CORS(cherrypy.serving.request.headers, cherrypy.serving.response.headers)
+
+
+def _safe_caching_headers():
+ """Adds `Origin`_ to the `Vary`_ header to ensure caching works properly.
+
+ Except in IE because it will disable caching completely. The caching
+ strategy in that case is out of the scope of this library.
+ https://blogs.msdn.microsoft.com/ieinternals/2009/06/17/vary-with-care/
+ """
+ uah = cherrypy.serving.request.headers.get('User-Agent', '')
+ ua = httpagentparser.detect(uah)
+ IE = 'Microsoft Internet Explorer'
+ if ua.get('browser', {}).get('name') != IE:
+ set_vary_header(cherrypy.serving.response, "Origin")
+
+
+tools = cherrypy._cptools.Toolbox("cors")
+tools.expose = cherrypy.Tool('before_handler', expose)
+tools.expose_public = cherrypy.Tool('before_handler', expose_public)
+tools.preflight = cherrypy.Tool('before_handler', preflight)
diff --git a/lib/dns/_asyncbackend.py b/lib/dns/_asyncbackend.py
index 49f14fed..f6760fd0 100644
--- a/lib/dns/_asyncbackend.py
+++ b/lib/dns/_asyncbackend.py
@@ -26,6 +26,10 @@ class NullContext:
class Socket: # pragma: no cover
+ def __init__(self, family: int, type: int):
+ self.family = family
+ self.type = type
+
async def close(self):
pass
@@ -46,9 +50,6 @@ class Socket: # pragma: no cover
class DatagramSocket(Socket): # pragma: no cover
- def __init__(self, family: int):
- self.family = family
-
async def sendto(self, what, destination, timeout):
raise NotImplementedError
diff --git a/lib/dns/_asyncio_backend.py b/lib/dns/_asyncio_backend.py
index 9d9ed369..6ab168de 100644
--- a/lib/dns/_asyncio_backend.py
+++ b/lib/dns/_asyncio_backend.py
@@ -42,7 +42,7 @@ class _DatagramProtocol:
if exc is None:
# EOF we triggered. Is there a better way to do this?
try:
- raise EOFError
+ raise EOFError("EOF")
except EOFError as e:
self.recvfrom.set_exception(e)
else:
@@ -64,7 +64,7 @@ async def _maybe_wait_for(awaitable, timeout):
class DatagramSocket(dns._asyncbackend.DatagramSocket):
def __init__(self, family, transport, protocol):
- super().__init__(family)
+ super().__init__(family, socket.SOCK_DGRAM)
self.transport = transport
self.protocol = protocol
@@ -99,7 +99,7 @@ class DatagramSocket(dns._asyncbackend.DatagramSocket):
class StreamSocket(dns._asyncbackend.StreamSocket):
def __init__(self, af, reader, writer):
- self.family = af
+ super().__init__(af, socket.SOCK_STREAM)
self.reader = reader
self.writer = writer
@@ -197,7 +197,7 @@ if dns._features.have("doh"):
family=socket.AF_UNSPEC,
**kwargs,
):
- if resolver is None:
+ if resolver is None and bootstrap_address is None:
# pylint: disable=import-outside-toplevel,redefined-outer-name
import dns.asyncresolver
diff --git a/lib/dns/_features.py b/lib/dns/_features.py
index 03ccaa77..fa6d4955 100644
--- a/lib/dns/_features.py
+++ b/lib/dns/_features.py
@@ -32,6 +32,9 @@ def _version_check(
package, minimum = requirement.split(">=")
try:
version = importlib.metadata.version(package)
+ # This shouldn't happen, but it apparently can.
+ if version is None:
+ return False
except Exception:
return False
t_version = _tuple_from_text(version)
@@ -82,10 +85,10 @@ def force(feature: str, enabled: bool) -> None:
_requirements: Dict[str, List[str]] = {
### BEGIN generated requirements
- "dnssec": ["cryptography>=41"],
+ "dnssec": ["cryptography>=43"],
"doh": ["httpcore>=1.0.0", "httpx>=0.26.0", "h2>=4.1.0"],
- "doq": ["aioquic>=0.9.25"],
- "idna": ["idna>=3.6"],
+ "doq": ["aioquic>=1.0.0"],
+ "idna": ["idna>=3.7"],
"trio": ["trio>=0.23"],
"wmi": ["wmi>=1.5.1"],
### END generated requirements
diff --git a/lib/dns/_trio_backend.py b/lib/dns/_trio_backend.py
index 398e3276..0ed904dd 100644
--- a/lib/dns/_trio_backend.py
+++ b/lib/dns/_trio_backend.py
@@ -30,13 +30,16 @@ _lltuple = dns.inet.low_level_address_tuple
class DatagramSocket(dns._asyncbackend.DatagramSocket):
- def __init__(self, socket):
- super().__init__(socket.family)
- self.socket = socket
+ def __init__(self, sock):
+ super().__init__(sock.family, socket.SOCK_DGRAM)
+ self.socket = sock
async def sendto(self, what, destination, timeout):
with _maybe_timeout(timeout):
- return await self.socket.sendto(what, destination)
+ if destination is None:
+ return await self.socket.send(what)
+ else:
+ return await self.socket.sendto(what, destination)
raise dns.exception.Timeout(
timeout=timeout
) # pragma: no cover lgtm[py/unreachable-statement]
@@ -61,7 +64,7 @@ class DatagramSocket(dns._asyncbackend.DatagramSocket):
class StreamSocket(dns._asyncbackend.StreamSocket):
def __init__(self, family, stream, tls=False):
- self.family = family
+ super().__init__(family, socket.SOCK_STREAM)
self.stream = stream
self.tls = tls
@@ -171,7 +174,7 @@ if dns._features.have("doh"):
family=socket.AF_UNSPEC,
**kwargs,
):
- if resolver is None:
+ if resolver is None and bootstrap_address is None:
# pylint: disable=import-outside-toplevel,redefined-outer-name
import dns.asyncresolver
@@ -205,7 +208,7 @@ class Backend(dns._asyncbackend.Backend):
try:
if source:
await s.bind(_lltuple(source, af))
- if socktype == socket.SOCK_STREAM:
+ if socktype == socket.SOCK_STREAM or destination is not None:
connected = False
with _maybe_timeout(timeout):
await s.connect(_lltuple(destination, af))
diff --git a/lib/dns/asyncquery.py b/lib/dns/asyncquery.py
index 4d9ab9ae..efad0fd7 100644
--- a/lib/dns/asyncquery.py
+++ b/lib/dns/asyncquery.py
@@ -19,10 +19,12 @@
import base64
import contextlib
+import random
import socket
import struct
import time
-from typing import Any, Dict, Optional, Tuple, Union
+import urllib.parse
+from typing import Any, Dict, Optional, Tuple, Union, cast
import dns.asyncbackend
import dns.exception
@@ -37,9 +39,11 @@ import dns.transaction
from dns._asyncbackend import NullContext
from dns.query import (
BadResponse,
+ HTTPVersion,
NoDOH,
NoDOQ,
UDPMode,
+ _check_status,
_compute_times,
_make_dot_ssl_context,
_matches_destination,
@@ -338,7 +342,7 @@ async def _read_exactly(sock, count, expiration):
while count > 0:
n = await sock.recv(count, _timeout(expiration))
if n == b"":
- raise EOFError
+ raise EOFError("EOF")
count = count - len(n)
s = s + n
return s
@@ -500,6 +504,20 @@ async def tls(
return response
+def _maybe_get_resolver(
+ resolver: Optional["dns.asyncresolver.Resolver"],
+) -> "dns.asyncresolver.Resolver":
+ # We need a separate method for this to avoid overriding the global
+ # variable "dns" with the as-yet undefined local variable "dns"
+ # in https().
+ if resolver is None:
+ # pylint: disable=import-outside-toplevel,redefined-outer-name
+ import dns.asyncresolver
+
+ resolver = dns.asyncresolver.Resolver()
+ return resolver
+
+
async def https(
q: dns.message.Message,
where: str,
@@ -515,7 +533,8 @@ async def https(
verify: Union[bool, str] = True,
bootstrap_address: Optional[str] = None,
resolver: Optional["dns.asyncresolver.Resolver"] = None,
- family: Optional[int] = socket.AF_UNSPEC,
+ family: int = socket.AF_UNSPEC,
+ http_version: HTTPVersion = HTTPVersion.DEFAULT,
) -> dns.message.Message:
"""Return the response obtained after sending a query via DNS-over-HTTPS.
@@ -529,26 +548,65 @@ async def https(
parameters, exceptions, and return type of this method.
"""
- if not have_doh:
- raise NoDOH # pragma: no cover
- if client and not isinstance(client, httpx.AsyncClient):
- raise ValueError("session parameter must be an httpx.AsyncClient")
-
- wire = q.to_wire()
try:
af = dns.inet.af_for_address(where)
except ValueError:
af = None
- transport = None
- headers = {"accept": "application/dns-message"}
if af is not None and dns.inet.is_address(where):
if af == socket.AF_INET:
- url = "https://{}:{}{}".format(where, port, path)
+ url = f"https://{where}:{port}{path}"
elif af == socket.AF_INET6:
- url = "https://[{}]:{}{}".format(where, port, path)
+ url = f"https://[{where}]:{port}{path}"
else:
url = where
+ extensions = {}
+ if bootstrap_address is None:
+ # pylint: disable=possibly-used-before-assignment
+ parsed = urllib.parse.urlparse(url)
+ if parsed.hostname is None:
+ raise ValueError("no hostname in URL")
+ if dns.inet.is_address(parsed.hostname):
+ bootstrap_address = parsed.hostname
+ extensions["sni_hostname"] = parsed.hostname
+ if parsed.port is not None:
+ port = parsed.port
+
+ if http_version == HTTPVersion.H3 or (
+ http_version == HTTPVersion.DEFAULT and not have_doh
+ ):
+ if bootstrap_address is None:
+ resolver = _maybe_get_resolver(resolver)
+ assert parsed.hostname is not None # for mypy
+ answers = await resolver.resolve_name(parsed.hostname, family)
+ bootstrap_address = random.choice(list(answers.addresses()))
+ return await _http3(
+ q,
+ bootstrap_address,
+ url,
+ timeout,
+ port,
+ source,
+ source_port,
+ one_rr_per_rrset,
+ ignore_trailing,
+ verify=verify,
+ post=post,
+ )
+
+ if not have_doh:
+ raise NoDOH # pragma: no cover
+ # pylint: disable=possibly-used-before-assignment
+ if client and not isinstance(client, httpx.AsyncClient):
+ raise ValueError("session parameter must be an httpx.AsyncClient")
+ # pylint: enable=possibly-used-before-assignment
+
+ wire = q.to_wire()
+ headers = {"accept": "application/dns-message"}
+
+ h1 = http_version in (HTTPVersion.H1, HTTPVersion.DEFAULT)
+ h2 = http_version in (HTTPVersion.H2, HTTPVersion.DEFAULT)
+
backend = dns.asyncbackend.get_default_backend()
if source is None:
@@ -557,24 +615,23 @@ async def https(
else:
local_address = source
local_port = source_port
- transport = backend.get_transport_class()(
- local_address=local_address,
- http1=True,
- http2=True,
- verify=verify,
- local_port=local_port,
- bootstrap_address=bootstrap_address,
- resolver=resolver,
- family=family,
- )
if client:
cm: contextlib.AbstractAsyncContextManager = NullContext(client)
else:
- cm = httpx.AsyncClient(
- http1=True, http2=True, verify=verify, transport=transport
+ transport = backend.get_transport_class()(
+ local_address=local_address,
+ http1=h1,
+ http2=h2,
+ verify=verify,
+ local_port=local_port,
+ bootstrap_address=bootstrap_address,
+ resolver=resolver,
+ family=family,
)
+ cm = httpx.AsyncClient(http1=h1, http2=h2, verify=verify, transport=transport)
+
async with cm as the_client:
# see https://tools.ietf.org/html/rfc8484#section-4.1.1 for DoH
# GET and POST examples
@@ -586,23 +643,33 @@ async def https(
}
)
response = await backend.wait_for(
- the_client.post(url, headers=headers, content=wire), timeout
+ the_client.post(
+ url,
+ headers=headers,
+ content=wire,
+ extensions=extensions,
+ ),
+ timeout,
)
else:
wire = base64.urlsafe_b64encode(wire).rstrip(b"=")
twire = wire.decode() # httpx does a repr() if we give it bytes
response = await backend.wait_for(
- the_client.get(url, headers=headers, params={"dns": twire}), timeout
+ the_client.get(
+ url,
+ headers=headers,
+ params={"dns": twire},
+ extensions=extensions,
+ ),
+ timeout,
)
# see https://tools.ietf.org/html/rfc8484#section-4.2.1 for info about DoH
# status codes
if response.status_code < 200 or response.status_code > 299:
raise ValueError(
- "{} responded with status code {}"
- "\nResponse body: {!r}".format(
- where, response.status_code, response.content
- )
+ f"{where} responded with status code {response.status_code}"
+ f"\nResponse body: {response.content!r}"
)
r = dns.message.from_wire(
response.content,
@@ -617,6 +684,181 @@ async def https(
return r
+async def _http3(
+ q: dns.message.Message,
+ where: str,
+ url: str,
+ timeout: Optional[float] = None,
+ port: int = 853,
+ source: Optional[str] = None,
+ source_port: int = 0,
+ one_rr_per_rrset: bool = False,
+ ignore_trailing: bool = False,
+ verify: Union[bool, str] = True,
+ backend: Optional[dns.asyncbackend.Backend] = None,
+ hostname: Optional[str] = None,
+ post: bool = True,
+) -> dns.message.Message:
+ if not dns.quic.have_quic:
+ raise NoDOH("DNS-over-HTTP3 is not available.") # pragma: no cover
+
+ url_parts = urllib.parse.urlparse(url)
+ hostname = url_parts.hostname
+ if url_parts.port is not None:
+ port = url_parts.port
+
+ q.id = 0
+ wire = q.to_wire()
+ (cfactory, mfactory) = dns.quic.factories_for_backend(backend)
+
+ async with cfactory() as context:
+ async with mfactory(
+ context, verify_mode=verify, server_name=hostname, h3=True
+ ) as the_manager:
+ the_connection = the_manager.connect(where, port, source, source_port)
+ (start, expiration) = _compute_times(timeout)
+ stream = await the_connection.make_stream(timeout)
+ async with stream:
+ # note that send_h3() does not need await
+ stream.send_h3(url, wire, post)
+ wire = await stream.receive(_remaining(expiration))
+ _check_status(stream.headers(), where, wire)
+ finish = time.time()
+ r = dns.message.from_wire(
+ wire,
+ keyring=q.keyring,
+ request_mac=q.request_mac,
+ one_rr_per_rrset=one_rr_per_rrset,
+ ignore_trailing=ignore_trailing,
+ )
+ r.time = max(finish - start, 0.0)
+ if not q.is_response(r):
+ raise BadResponse
+ return r
+
+
+async def quic(
+ q: dns.message.Message,
+ where: str,
+ timeout: Optional[float] = None,
+ port: int = 853,
+ source: Optional[str] = None,
+ source_port: int = 0,
+ one_rr_per_rrset: bool = False,
+ ignore_trailing: bool = False,
+ connection: Optional[dns.quic.AsyncQuicConnection] = None,
+ verify: Union[bool, str] = True,
+ backend: Optional[dns.asyncbackend.Backend] = None,
+ hostname: Optional[str] = None,
+ server_hostname: Optional[str] = None,
+) -> dns.message.Message:
+ """Return the response obtained after sending an asynchronous query via
+ DNS-over-QUIC.
+
+ *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``,
+ the default, then dnspython will use the default backend.
+
+ See :py:func:`dns.query.quic()` for the documentation of the other
+ parameters, exceptions, and return type of this method.
+ """
+
+ if not dns.quic.have_quic:
+ raise NoDOQ("DNS-over-QUIC is not available.") # pragma: no cover
+
+ if server_hostname is not None and hostname is None:
+ hostname = server_hostname
+
+ q.id = 0
+ wire = q.to_wire()
+ the_connection: dns.quic.AsyncQuicConnection
+ if connection:
+ cfactory = dns.quic.null_factory
+ mfactory = dns.quic.null_factory
+ the_connection = connection
+ else:
+ (cfactory, mfactory) = dns.quic.factories_for_backend(backend)
+
+ async with cfactory() as context:
+ async with mfactory(
+ context,
+ verify_mode=verify,
+ server_name=server_hostname,
+ ) as the_manager:
+ if not connection:
+ the_connection = the_manager.connect(where, port, source, source_port)
+ (start, expiration) = _compute_times(timeout)
+ stream = await the_connection.make_stream(timeout)
+ async with stream:
+ await stream.send(wire, True)
+ wire = await stream.receive(_remaining(expiration))
+ finish = time.time()
+ r = dns.message.from_wire(
+ wire,
+ keyring=q.keyring,
+ request_mac=q.request_mac,
+ one_rr_per_rrset=one_rr_per_rrset,
+ ignore_trailing=ignore_trailing,
+ )
+ r.time = max(finish - start, 0.0)
+ if not q.is_response(r):
+ raise BadResponse
+ return r
+
+
+async def _inbound_xfr(
+ txn_manager: dns.transaction.TransactionManager,
+ s: dns.asyncbackend.Socket,
+ query: dns.message.Message,
+ serial: Optional[int],
+ timeout: Optional[float],
+ expiration: float,
+) -> Any:
+ """Given a socket, does the zone transfer."""
+ rdtype = query.question[0].rdtype
+ is_ixfr = rdtype == dns.rdatatype.IXFR
+ origin = txn_manager.from_wire_origin()
+ wire = query.to_wire()
+ is_udp = s.type == socket.SOCK_DGRAM
+ if is_udp:
+ udp_sock = cast(dns.asyncbackend.DatagramSocket, s)
+ await udp_sock.sendto(wire, None, _timeout(expiration))
+ else:
+ tcp_sock = cast(dns.asyncbackend.StreamSocket, s)
+ tcpmsg = struct.pack("!H", len(wire)) + wire
+ await tcp_sock.sendall(tcpmsg, expiration)
+ with dns.xfr.Inbound(txn_manager, rdtype, serial, is_udp) as inbound:
+ done = False
+ tsig_ctx = None
+ while not done:
+ (_, mexpiration) = _compute_times(timeout)
+ if mexpiration is None or (
+ expiration is not None and mexpiration > expiration
+ ):
+ mexpiration = expiration
+ if is_udp:
+ timeout = _timeout(mexpiration)
+ (rwire, _) = await udp_sock.recvfrom(65535, timeout)
+ else:
+ ldata = await _read_exactly(tcp_sock, 2, mexpiration)
+ (l,) = struct.unpack("!H", ldata)
+ rwire = await _read_exactly(tcp_sock, l, mexpiration)
+ r = dns.message.from_wire(
+ rwire,
+ keyring=query.keyring,
+ request_mac=query.mac,
+ xfr=True,
+ origin=origin,
+ tsig_ctx=tsig_ctx,
+ multi=(not is_udp),
+ one_rr_per_rrset=is_ixfr,
+ )
+ done = inbound.process_message(r)
+ yield r
+ tsig_ctx = r.tsig_ctx
+ if query.keyring and not r.had_tsig:
+ raise dns.exception.FormError("missing TSIG")
+
+
async def inbound_xfr(
where: str,
txn_manager: dns.transaction.TransactionManager,
@@ -642,139 +884,30 @@ async def inbound_xfr(
(query, serial) = dns.xfr.make_query(txn_manager)
else:
serial = dns.xfr.extract_serial_from_query(query)
- rdtype = query.question[0].rdtype
- is_ixfr = rdtype == dns.rdatatype.IXFR
- origin = txn_manager.from_wire_origin()
- wire = query.to_wire()
af = dns.inet.af_for_address(where)
stuple = _source_tuple(af, source, source_port)
dtuple = (where, port)
+ if not backend:
+ backend = dns.asyncbackend.get_default_backend()
(_, expiration) = _compute_times(lifetime)
- retry = True
- while retry:
- retry = False
- if is_ixfr and udp_mode != UDPMode.NEVER:
- sock_type = socket.SOCK_DGRAM
- is_udp = True
- else:
- sock_type = socket.SOCK_STREAM
- is_udp = False
- if not backend:
- backend = dns.asyncbackend.get_default_backend()
+ if query.question[0].rdtype == dns.rdatatype.IXFR and udp_mode != UDPMode.NEVER:
s = await backend.make_socket(
- af, sock_type, 0, stuple, dtuple, _timeout(expiration)
+ af, socket.SOCK_DGRAM, 0, stuple, dtuple, _timeout(expiration)
)
async with s:
- if is_udp:
- await s.sendto(wire, dtuple, _timeout(expiration))
- else:
- tcpmsg = struct.pack("!H", len(wire)) + wire
- await s.sendall(tcpmsg, expiration)
- with dns.xfr.Inbound(txn_manager, rdtype, serial, is_udp) as inbound:
- done = False
- tsig_ctx = None
- while not done:
- (_, mexpiration) = _compute_times(timeout)
- if mexpiration is None or (
- expiration is not None and mexpiration > expiration
- ):
- mexpiration = expiration
- if is_udp:
- destination = _lltuple((where, port), af)
- while True:
- timeout = _timeout(mexpiration)
- (rwire, from_address) = await s.recvfrom(65535, timeout)
- if _matches_destination(
- af, from_address, destination, True
- ):
- break
- else:
- ldata = await _read_exactly(s, 2, mexpiration)
- (l,) = struct.unpack("!H", ldata)
- rwire = await _read_exactly(s, l, mexpiration)
- is_ixfr = rdtype == dns.rdatatype.IXFR
- r = dns.message.from_wire(
- rwire,
- keyring=query.keyring,
- request_mac=query.mac,
- xfr=True,
- origin=origin,
- tsig_ctx=tsig_ctx,
- multi=(not is_udp),
- one_rr_per_rrset=is_ixfr,
- )
- try:
- done = inbound.process_message(r)
- except dns.xfr.UseTCP:
- assert is_udp # should not happen if we used TCP!
- if udp_mode == UDPMode.ONLY:
- raise
- done = True
- retry = True
- udp_mode = UDPMode.NEVER
- continue
- tsig_ctx = r.tsig_ctx
- if not retry and query.keyring and not r.had_tsig:
- raise dns.exception.FormError("missing TSIG")
+ try:
+ async for _ in _inbound_xfr(
+ txn_manager, s, query, serial, timeout, expiration
+ ):
+ pass
+ return
+ except dns.xfr.UseTCP:
+ if udp_mode == UDPMode.ONLY:
+ raise
-
-async def quic(
- q: dns.message.Message,
- where: str,
- timeout: Optional[float] = None,
- port: int = 853,
- source: Optional[str] = None,
- source_port: int = 0,
- one_rr_per_rrset: bool = False,
- ignore_trailing: bool = False,
- connection: Optional[dns.quic.AsyncQuicConnection] = None,
- verify: Union[bool, str] = True,
- backend: Optional[dns.asyncbackend.Backend] = None,
- server_hostname: Optional[str] = None,
-) -> dns.message.Message:
- """Return the response obtained after sending an asynchronous query via
- DNS-over-QUIC.
-
- *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``,
- the default, then dnspython will use the default backend.
-
- See :py:func:`dns.query.quic()` for the documentation of the other
- parameters, exceptions, and return type of this method.
- """
-
- if not dns.quic.have_quic:
- raise NoDOQ("DNS-over-QUIC is not available.") # pragma: no cover
-
- q.id = 0
- wire = q.to_wire()
- the_connection: dns.quic.AsyncQuicConnection
- if connection:
- cfactory = dns.quic.null_factory
- mfactory = dns.quic.null_factory
- the_connection = connection
- else:
- (cfactory, mfactory) = dns.quic.factories_for_backend(backend)
-
- async with cfactory() as context:
- async with mfactory(
- context, verify_mode=verify, server_name=server_hostname
- ) as the_manager:
- if not connection:
- the_connection = the_manager.connect(where, port, source, source_port)
- (start, expiration) = _compute_times(timeout)
- stream = await the_connection.make_stream(timeout)
- async with stream:
- await stream.send(wire, True)
- wire = await stream.receive(_remaining(expiration))
- finish = time.time()
- r = dns.message.from_wire(
- wire,
- keyring=q.keyring,
- request_mac=q.request_mac,
- one_rr_per_rrset=one_rr_per_rrset,
- ignore_trailing=ignore_trailing,
- )
- r.time = max(finish - start, 0.0)
- if not q.is_response(r):
- raise BadResponse
- return r
+ s = await backend.make_socket(
+ af, socket.SOCK_STREAM, 0, stuple, dtuple, _timeout(expiration)
+ )
+ async with s:
+ async for _ in _inbound_xfr(txn_manager, s, query, serial, timeout, expiration):
+ pass
diff --git a/lib/dns/dnssec.py b/lib/dns/dnssec.py
index e49c3b79..b69d0a12 100644
--- a/lib/dns/dnssec.py
+++ b/lib/dns/dnssec.py
@@ -118,6 +118,7 @@ def key_id(key: Union[DNSKEY, CDNSKEY]) -> int:
"""
rdata = key.to_wire()
+ assert rdata is not None # for mypy
if key.algorithm == Algorithm.RSAMD5:
return (rdata[-3] << 8) + rdata[-2]
else:
@@ -224,7 +225,7 @@ def make_ds(
if isinstance(algorithm, str):
algorithm = DSDigest[algorithm.upper()]
except Exception:
- raise UnsupportedAlgorithm('unsupported algorithm "%s"' % algorithm)
+ raise UnsupportedAlgorithm(f'unsupported algorithm "{algorithm}"')
if validating:
check = policy.ok_to_validate_ds
else:
@@ -240,14 +241,15 @@ def make_ds(
elif algorithm == DSDigest.SHA384:
dshash = hashlib.sha384()
else:
- raise UnsupportedAlgorithm('unsupported algorithm "%s"' % algorithm)
+ raise UnsupportedAlgorithm(f'unsupported algorithm "{algorithm}"')
if isinstance(name, str):
name = dns.name.from_text(name, origin)
wire = name.canonicalize().to_wire()
- assert wire is not None
+ kwire = key.to_wire(origin=origin)
+ assert wire is not None and kwire is not None # for mypy
dshash.update(wire)
- dshash.update(key.to_wire(origin=origin))
+ dshash.update(kwire)
digest = dshash.digest()
dsrdata = struct.pack("!HBB", key_id(key), key.algorithm, algorithm) + digest
@@ -323,6 +325,7 @@ def _get_rrname_rdataset(
def _validate_signature(sig: bytes, data: bytes, key: DNSKEY) -> None:
+ # pylint: disable=possibly-used-before-assignment
public_cls = get_algorithm_cls_from_dnskey(key).public_cls
try:
public_key = public_cls.from_dnskey(key)
@@ -387,6 +390,7 @@ def _validate_rrsig(
data = _make_rrsig_signature_data(rrset, rrsig, origin)
+ # pylint: disable=possibly-used-before-assignment
for candidate_key in candidate_keys:
if not policy.ok_to_validate(candidate_key):
continue
@@ -484,6 +488,7 @@ def _sign(
verify: bool = False,
policy: Optional[Policy] = None,
origin: Optional[dns.name.Name] = None,
+ deterministic: bool = True,
) -> RRSIG:
"""Sign RRset using private key.
@@ -523,6 +528,10 @@ def _sign(
names in the rrset (including its owner name) must be absolute; otherwise the
specified origin will be used to make names absolute when signing.
+ *deterministic*, a ``bool``. If ``True``, the default, use deterministic
+ (reproducible) signatures when supported by the algorithm used for signing.
+ Currently, this only affects ECDSA.
+
Raises ``DeniedByPolicy`` if the signature is denied by policy.
"""
@@ -580,6 +589,7 @@ def _sign(
data = dns.dnssec._make_rrsig_signature_data(rrset, rrsig_template, origin)
+ # pylint: disable=possibly-used-before-assignment
if isinstance(private_key, GenericPrivateKey):
signing_key = private_key
else:
@@ -589,7 +599,7 @@ def _sign(
except UnsupportedAlgorithm:
raise TypeError("Unsupported key algorithm")
- signature = signing_key.sign(data, verify)
+ signature = signing_key.sign(data, verify, deterministic)
return cast(RRSIG, rrsig_template.replace(signature=signature))
@@ -629,7 +639,9 @@ def _make_rrsig_signature_data(
rrname, rdataset = _get_rrname_rdataset(rrset)
data = b""
- data += rrsig.to_wire(origin=signer)[:18]
+ wire = rrsig.to_wire(origin=signer)
+ assert wire is not None # for mypy
+ data += wire[:18]
data += rrsig.signer.to_digestable(signer)
# Derelativize the name before considering labels.
@@ -686,6 +698,7 @@ def _make_dnskey(
algorithm = Algorithm.make(algorithm)
+ # pylint: disable=possibly-used-before-assignment
if isinstance(public_key, GenericPublicKey):
return public_key.to_dnskey(flags=flags, protocol=protocol)
else:
@@ -832,7 +845,7 @@ def make_ds_rdataset(
if isinstance(algorithm, str):
algorithm = DSDigest[algorithm.upper()]
except Exception:
- raise UnsupportedAlgorithm('unsupported algorithm "%s"' % algorithm)
+ raise UnsupportedAlgorithm(f'unsupported algorithm "{algorithm}"')
_algorithms.add(algorithm)
if rdataset.rdtype == dns.rdatatype.CDS:
@@ -950,6 +963,7 @@ def default_rrset_signer(
lifetime: Optional[int] = None,
policy: Optional[Policy] = None,
origin: Optional[dns.name.Name] = None,
+ deterministic: bool = True,
) -> None:
"""Default RRset signer"""
@@ -975,6 +989,7 @@ def default_rrset_signer(
signer=signer,
policy=policy,
origin=origin,
+ deterministic=deterministic,
)
txn.add(rrset.name, rrset.ttl, rrsig)
@@ -991,6 +1006,7 @@ def sign_zone(
nsec3: Optional[NSEC3PARAM] = None,
rrset_signer: Optional[RRsetSigner] = None,
policy: Optional[Policy] = None,
+ deterministic: bool = True,
) -> None:
"""Sign zone.
@@ -1030,6 +1046,10 @@ def sign_zone(
function requires two arguments: transaction and RRset. If the not specified,
``dns.dnssec.default_rrset_signer`` will be used.
+ *deterministic*, a ``bool``. If ``True``, the default, use deterministic
+ (reproducible) signatures when supported by the algorithm used for signing.
+ Currently, this only affects ECDSA.
+
Returns ``None``.
"""
@@ -1056,6 +1076,9 @@ def sign_zone(
else:
cm = zone.writer()
+ if zone.origin is None:
+ raise ValueError("no zone origin")
+
with cm as _txn:
if add_dnskey:
if dnskey_ttl is None:
@@ -1081,6 +1104,7 @@ def sign_zone(
lifetime=lifetime,
policy=policy,
origin=zone.origin,
+ deterministic=deterministic,
)
return _sign_zone_nsec(zone, _txn, _rrset_signer)
diff --git a/lib/dns/dnssecalgs/__init__.py b/lib/dns/dnssecalgs/__init__.py
index 3d9181a7..602367e3 100644
--- a/lib/dns/dnssecalgs/__init__.py
+++ b/lib/dns/dnssecalgs/__init__.py
@@ -26,6 +26,7 @@ AlgorithmPrefix = Optional[Union[bytes, dns.name.Name]]
algorithms: Dict[Tuple[Algorithm, AlgorithmPrefix], Type[GenericPrivateKey]] = {}
if _have_cryptography:
+ # pylint: disable=possibly-used-before-assignment
algorithms.update(
{
(Algorithm.RSAMD5, None): PrivateRSAMD5,
@@ -59,7 +60,7 @@ def get_algorithm_cls(
if cls:
return cls
raise UnsupportedAlgorithm(
- 'algorithm "%s" not supported by dnspython' % Algorithm.to_text(algorithm)
+ f'algorithm "{Algorithm.to_text(algorithm)}" not supported by dnspython'
)
diff --git a/lib/dns/dnssecalgs/base.py b/lib/dns/dnssecalgs/base.py
index e990575a..752ee480 100644
--- a/lib/dns/dnssecalgs/base.py
+++ b/lib/dns/dnssecalgs/base.py
@@ -65,7 +65,12 @@ class GenericPrivateKey(ABC):
pass
@abstractmethod
- def sign(self, data: bytes, verify: bool = False) -> bytes:
+ def sign(
+ self,
+ data: bytes,
+ verify: bool = False,
+ deterministic: bool = True,
+ ) -> bytes:
"""Sign DNSSEC data"""
@abstractmethod
diff --git a/lib/dns/dnssecalgs/dsa.py b/lib/dns/dnssecalgs/dsa.py
index 0fe4690d..adca3def 100644
--- a/lib/dns/dnssecalgs/dsa.py
+++ b/lib/dns/dnssecalgs/dsa.py
@@ -68,7 +68,12 @@ class PrivateDSA(CryptographyPrivateKey):
key_cls = dsa.DSAPrivateKey
public_cls = PublicDSA
- def sign(self, data: bytes, verify: bool = False) -> bytes:
+ def sign(
+ self,
+ data: bytes,
+ verify: bool = False,
+ deterministic: bool = True,
+ ) -> bytes:
"""Sign using a private key per RFC 2536, section 3."""
public_dsa_key = self.key.public_key()
if public_dsa_key.key_size > 1024:
diff --git a/lib/dns/dnssecalgs/ecdsa.py b/lib/dns/dnssecalgs/ecdsa.py
index a31d79f2..86d5764c 100644
--- a/lib/dns/dnssecalgs/ecdsa.py
+++ b/lib/dns/dnssecalgs/ecdsa.py
@@ -47,9 +47,17 @@ class PrivateECDSA(CryptographyPrivateKey):
key_cls = ec.EllipticCurvePrivateKey
public_cls = PublicECDSA
- def sign(self, data: bytes, verify: bool = False) -> bytes:
+ def sign(
+ self,
+ data: bytes,
+ verify: bool = False,
+ deterministic: bool = True,
+ ) -> bytes:
"""Sign using a private key per RFC 6605, section 4."""
- der_signature = self.key.sign(data, ec.ECDSA(self.public_cls.chosen_hash))
+ algorithm = ec.ECDSA(
+ self.public_cls.chosen_hash, deterministic_signing=deterministic
+ )
+ der_signature = self.key.sign(data, algorithm)
dsa_r, dsa_s = utils.decode_dss_signature(der_signature)
signature = int.to_bytes(
dsa_r, length=self.public_cls.octets, byteorder="big"
diff --git a/lib/dns/dnssecalgs/eddsa.py b/lib/dns/dnssecalgs/eddsa.py
index 70505342..604bcbfe 100644
--- a/lib/dns/dnssecalgs/eddsa.py
+++ b/lib/dns/dnssecalgs/eddsa.py
@@ -29,7 +29,12 @@ class PublicEDDSA(CryptographyPublicKey):
class PrivateEDDSA(CryptographyPrivateKey):
public_cls: Type[PublicEDDSA]
- def sign(self, data: bytes, verify: bool = False) -> bytes:
+ def sign(
+ self,
+ data: bytes,
+ verify: bool = False,
+ deterministic: bool = True,
+ ) -> bytes:
"""Sign using a private key per RFC 8080, section 4."""
signature = self.key.sign(data)
if verify:
diff --git a/lib/dns/dnssecalgs/rsa.py b/lib/dns/dnssecalgs/rsa.py
index e95dcf1d..27537aad 100644
--- a/lib/dns/dnssecalgs/rsa.py
+++ b/lib/dns/dnssecalgs/rsa.py
@@ -56,7 +56,12 @@ class PrivateRSA(CryptographyPrivateKey):
public_cls = PublicRSA
default_public_exponent = 65537
- def sign(self, data: bytes, verify: bool = False) -> bytes:
+ def sign(
+ self,
+ data: bytes,
+ verify: bool = False,
+ deterministic: bool = True,
+ ) -> bytes:
"""Sign using a private key per RFC 3110, section 3."""
signature = self.key.sign(data, padding.PKCS1v15(), self.public_cls.chosen_hash)
if verify:
diff --git a/lib/dns/edns.py b/lib/dns/edns.py
index 776e5eeb..f7d9ff99 100644
--- a/lib/dns/edns.py
+++ b/lib/dns/edns.py
@@ -52,6 +52,8 @@ class OptionType(dns.enum.IntEnum):
CHAIN = 13
#: EDE (extended-dns-error)
EDE = 15
+ #: REPORTCHANNEL
+ REPORTCHANNEL = 18
@classmethod
def _maximum(cls):
@@ -222,7 +224,7 @@ class ECSOption(Option): # lgtm[py/missing-equals]
self.addrdata = self.addrdata[:-1] + last
def to_text(self) -> str:
- return "ECS {}/{} scope/{}".format(self.address, self.srclen, self.scopelen)
+ return f"ECS {self.address}/{self.srclen} scope/{self.scopelen}"
@staticmethod
def from_text(text: str) -> Option:
@@ -255,10 +257,10 @@ class ECSOption(Option): # lgtm[py/missing-equals]
ecs_text = tokens[0]
elif len(tokens) == 2:
if tokens[0] != optional_prefix:
- raise ValueError('could not parse ECS from "{}"'.format(text))
+ raise ValueError(f'could not parse ECS from "{text}"')
ecs_text = tokens[1]
else:
- raise ValueError('could not parse ECS from "{}"'.format(text))
+ raise ValueError(f'could not parse ECS from "{text}"')
n_slashes = ecs_text.count("/")
if n_slashes == 1:
address, tsrclen = ecs_text.split("/")
@@ -266,18 +268,16 @@ class ECSOption(Option): # lgtm[py/missing-equals]
elif n_slashes == 2:
address, tsrclen, tscope = ecs_text.split("/")
else:
- raise ValueError('could not parse ECS from "{}"'.format(text))
+ raise ValueError(f'could not parse ECS from "{text}"')
try:
scope = int(tscope)
except ValueError:
- raise ValueError(
- "invalid scope " + '"{}": scope must be an integer'.format(tscope)
- )
+ raise ValueError("invalid scope " + f'"{tscope}": scope must be an integer')
try:
srclen = int(tsrclen)
except ValueError:
raise ValueError(
- "invalid srclen " + '"{}": srclen must be an integer'.format(tsrclen)
+ "invalid srclen " + f'"{tsrclen}": srclen must be an integer'
)
return ECSOption(address, srclen, scope)
@@ -430,10 +430,65 @@ class NSIDOption(Option):
return cls(parser.get_remaining())
+class CookieOption(Option):
+ def __init__(self, client: bytes, server: bytes):
+ super().__init__(dns.edns.OptionType.COOKIE)
+ self.client = client
+ self.server = server
+ if len(client) != 8:
+ raise ValueError("client cookie must be 8 bytes")
+ if len(server) != 0 and (len(server) < 8 or len(server) > 32):
+ raise ValueError("server cookie must be empty or between 8 and 32 bytes")
+
+ def to_wire(self, file: Any = None) -> Optional[bytes]:
+ if file:
+ file.write(self.client)
+ if len(self.server) > 0:
+ file.write(self.server)
+ return None
+ else:
+ return self.client + self.server
+
+ def to_text(self) -> str:
+ client = binascii.hexlify(self.client).decode()
+ if len(self.server) > 0:
+ server = binascii.hexlify(self.server).decode()
+ else:
+ server = ""
+ return f"COOKIE {client}{server}"
+
+ @classmethod
+ def from_wire_parser(
+ cls, otype: Union[OptionType, str], parser: dns.wire.Parser
+ ) -> Option:
+ return cls(parser.get_bytes(8), parser.get_remaining())
+
+
+class ReportChannelOption(Option):
+ # RFC 9567
+ def __init__(self, agent_domain: dns.name.Name):
+ super().__init__(OptionType.REPORTCHANNEL)
+ self.agent_domain = agent_domain
+
+ def to_wire(self, file: Any = None) -> Optional[bytes]:
+ return self.agent_domain.to_wire(file)
+
+ def to_text(self) -> str:
+ return "REPORTCHANNEL " + self.agent_domain.to_text()
+
+ @classmethod
+ def from_wire_parser(
+ cls, otype: Union[OptionType, str], parser: dns.wire.Parser
+ ) -> Option:
+ return cls(parser.get_name())
+
+
_type_to_class: Dict[OptionType, Any] = {
OptionType.ECS: ECSOption,
OptionType.EDE: EDEOption,
OptionType.NSID: NSIDOption,
+ OptionType.COOKIE: CookieOption,
+ OptionType.REPORTCHANNEL: ReportChannelOption,
}
@@ -512,5 +567,6 @@ KEEPALIVE = OptionType.KEEPALIVE
PADDING = OptionType.PADDING
CHAIN = OptionType.CHAIN
EDE = OptionType.EDE
+REPORTCHANNEL = OptionType.REPORTCHANNEL
### END generated OptionType constants
diff --git a/lib/dns/exception.py b/lib/dns/exception.py
index 6982373d..223f2d68 100644
--- a/lib/dns/exception.py
+++ b/lib/dns/exception.py
@@ -81,7 +81,7 @@ class DNSException(Exception):
if kwargs:
assert (
set(kwargs.keys()) == self.supp_kwargs
- ), "following set of keyword args is required: %s" % (self.supp_kwargs)
+ ), f"following set of keyword args is required: {self.supp_kwargs}"
return kwargs
def _fmt_kwargs(self, **kwargs):
diff --git a/lib/dns/grange.py b/lib/dns/grange.py
index 3a52278f..a967ca41 100644
--- a/lib/dns/grange.py
+++ b/lib/dns/grange.py
@@ -54,7 +54,7 @@ def from_text(text: str) -> Tuple[int, int, int]:
elif c.isdigit():
cur += c
else:
- raise dns.exception.SyntaxError("Could not parse %s" % (c))
+ raise dns.exception.SyntaxError(f"Could not parse {c}")
if state == 0:
raise dns.exception.SyntaxError("no stop value specified")
diff --git a/lib/dns/ipv6.py b/lib/dns/ipv6.py
index 44a10639..4dd1d1ca 100644
--- a/lib/dns/ipv6.py
+++ b/lib/dns/ipv6.py
@@ -143,9 +143,7 @@ def inet_aton(text: Union[str, bytes], ignore_scope: bool = False) -> bytes:
if m is not None:
b = dns.ipv4.inet_aton(m.group(2))
btext = (
- "{}:{:02x}{:02x}:{:02x}{:02x}".format(
- m.group(1).decode(), b[0], b[1], b[2], b[3]
- )
+ f"{m.group(1).decode()}:{b[0]:02x}{b[1]:02x}:{b[2]:02x}{b[3]:02x}"
).encode()
#
# Try to turn '::' into ':'; if no match try to
diff --git a/lib/dns/message.py b/lib/dns/message.py
index 44cacbd9..e978a0a2 100644
--- a/lib/dns/message.py
+++ b/lib/dns/message.py
@@ -18,9 +18,10 @@
"""DNS Messages"""
import contextlib
+import enum
import io
import time
-from typing import Any, Dict, List, Optional, Tuple, Union
+from typing import Any, Dict, List, Optional, Tuple, Union, cast
import dns.edns
import dns.entropy
@@ -161,6 +162,7 @@ class Message:
self.index: IndexType = {}
self.errors: List[MessageError] = []
self.time = 0.0
+ self.wire: Optional[bytes] = None
@property
def question(self) -> List[dns.rrset.RRset]:
@@ -220,16 +222,16 @@ class Message:
s = io.StringIO()
s.write("id %d\n" % self.id)
- s.write("opcode %s\n" % dns.opcode.to_text(self.opcode()))
- s.write("rcode %s\n" % dns.rcode.to_text(self.rcode()))
- s.write("flags %s\n" % dns.flags.to_text(self.flags))
+ s.write(f"opcode {dns.opcode.to_text(self.opcode())}\n")
+ s.write(f"rcode {dns.rcode.to_text(self.rcode())}\n")
+ s.write(f"flags {dns.flags.to_text(self.flags)}\n")
if self.edns >= 0:
- s.write("edns %s\n" % self.edns)
+ s.write(f"edns {self.edns}\n")
if self.ednsflags != 0:
- s.write("eflags %s\n" % dns.flags.edns_to_text(self.ednsflags))
+ s.write(f"eflags {dns.flags.edns_to_text(self.ednsflags)}\n")
s.write("payload %d\n" % self.payload)
for opt in self.options:
- s.write("option %s\n" % opt.to_text())
+ s.write(f"option {opt.to_text()}\n")
for name, which in self._section_enum.__members__.items():
s.write(f";{name}\n")
for rrset in self.section_from_number(which):
@@ -645,6 +647,7 @@ class Message:
if multi:
self.tsig_ctx = ctx
wire = r.get_wire()
+ self.wire = wire
if prepend_length:
wire = len(wire).to_bytes(2, "big") + wire
return wire
@@ -912,6 +915,14 @@ class Message:
self.flags &= 0x87FF
self.flags |= dns.opcode.to_flags(opcode)
+ def get_options(self, otype: dns.edns.OptionType) -> List[dns.edns.Option]:
+ """Return the list of options of the specified type."""
+ return [option for option in self.options if option.otype == otype]
+
+ def extended_errors(self) -> List[dns.edns.EDEOption]:
+ """Return the list of Extended DNS Error (EDE) options in the message"""
+ return cast(List[dns.edns.EDEOption], self.get_options(dns.edns.OptionType.EDE))
+
def _get_one_rr_per_rrset(self, value):
# What the caller picked is fine.
return value
@@ -1192,9 +1203,9 @@ class _WireReader:
if rdtype == dns.rdatatype.OPT:
self.message.opt = dns.rrset.from_rdata(name, ttl, rd)
elif rdtype == dns.rdatatype.TSIG:
- if self.keyring is None:
+ if self.keyring is None or self.keyring is True:
raise UnknownTSIGKey("got signed message without keyring")
- if isinstance(self.keyring, dict):
+ elif isinstance(self.keyring, dict):
key = self.keyring.get(absolute_name)
if isinstance(key, bytes):
key = dns.tsig.Key(absolute_name, key, rd.algorithm)
@@ -1203,19 +1214,20 @@ class _WireReader:
else:
key = self.keyring
if key is None:
- raise UnknownTSIGKey("key '%s' unknown" % name)
- self.message.keyring = key
- self.message.tsig_ctx = dns.tsig.validate(
- self.parser.wire,
- key,
- absolute_name,
- rd,
- int(time.time()),
- self.message.request_mac,
- rr_start,
- self.message.tsig_ctx,
- self.multi,
- )
+ raise UnknownTSIGKey(f"key '{name}' unknown")
+ if key:
+ self.message.keyring = key
+ self.message.tsig_ctx = dns.tsig.validate(
+ self.parser.wire,
+ key,
+ absolute_name,
+ rd,
+ int(time.time()),
+ self.message.request_mac,
+ rr_start,
+ self.message.tsig_ctx,
+ self.multi,
+ )
self.message.tsig = dns.rrset.from_rdata(absolute_name, 0, rd)
else:
rrset = self.message.find_rrset(
@@ -1251,6 +1263,7 @@ class _WireReader:
factory = _message_factory_from_opcode(dns.opcode.from_flags(flags))
self.message = factory(id=id)
self.message.flags = dns.flags.Flag(flags)
+ self.message.wire = self.parser.wire
self.initialize_message(self.message)
self.one_rr_per_rrset = self.message._get_one_rr_per_rrset(
self.one_rr_per_rrset
@@ -1290,8 +1303,10 @@ def from_wire(
) -> Message:
"""Convert a DNS wire format message into a message object.
- *keyring*, a ``dns.tsig.Key`` or ``dict``, the key or keyring to use if the message
- is signed.
+ *keyring*, a ``dns.tsig.Key``, ``dict``, ``bool``, or ``None``, the key or keyring
+ to use if the message is signed. If ``None`` or ``True``, then trying to decode
+ a message with a TSIG will fail as it cannot be validated. If ``False``, then
+ TSIG validation is disabled.
*request_mac*, a ``bytes`` or ``None``. If the message is a response to a
TSIG-signed request, *request_mac* should be set to the MAC of that request.
@@ -1811,6 +1826,16 @@ def make_query(
return m
+class CopyMode(enum.Enum):
+ """
+ How should sections be copied when making an update response?
+ """
+
+ NOTHING = 0
+ QUESTION = 1
+ EVERYTHING = 2
+
+
def make_response(
query: Message,
recursion_available: bool = False,
@@ -1818,13 +1843,14 @@ def make_response(
fudge: int = 300,
tsig_error: int = 0,
pad: Optional[int] = None,
+ copy_mode: Optional[CopyMode] = None,
) -> Message:
"""Make a message which is a response for the specified query.
The message returned is really a response skeleton; it has all of the infrastructure
required of a response, but none of the content.
- The response's question section is a shallow copy of the query's question section,
- so the query's question RRsets should not be changed.
+ Response section(s) which are copied are shallow copies of the matching section(s)
+ in the query, so the query's RRsets should not be changed.
*query*, a ``dns.message.Message``, the query to respond to.
@@ -1837,25 +1863,44 @@ def make_response(
*tsig_error*, an ``int``, the TSIG error.
*pad*, a non-negative ``int`` or ``None``. If 0, the default, do not pad; otherwise
- if not ``None`` add padding bytes to make the message size a multiple of *pad*.
- Note that if padding is non-zero, an EDNS PADDING option will always be added to the
+ if not ``None`` add padding bytes to make the message size a multiple of *pad*. Note
+ that if padding is non-zero, an EDNS PADDING option will always be added to the
message. If ``None``, add padding following RFC 8467, namely if the request is
padded, pad the response to 468 otherwise do not pad.
+ *copy_mode*, a ``dns.message.CopyMode`` or ``None``, determines how sections are
+ copied. The default, ``None`` copies sections according to the default for the
+ message's opcode, which is currently ``dns.message.CopyMode.QUESTION`` for all
+ opcodes. ``dns.message.CopyMode.QUESTION`` copies only the question section.
+ ``dns.message.CopyMode.EVERYTHING`` copies all sections other than OPT or TSIG
+ records, which are created appropriately if needed. ``dns.message.CopyMode.NOTHING``
+ copies no sections; note that this mode is for server testing purposes and is
+ otherwise not recommended for use. In particular, ``dns.message.is_response()``
+ will be ``False`` if you create a response this way and the rcode is not
+ ``FORMERR``, ``SERVFAIL``, ``NOTIMP``, or ``REFUSED``.
+
Returns a ``dns.message.Message`` object whose specific class is appropriate for the
- query. For example, if query is a ``dns.update.UpdateMessage``, response will be
- too.
+ query. For example, if query is a ``dns.update.UpdateMessage``, the response will
+ be one too.
"""
if query.flags & dns.flags.QR:
raise dns.exception.FormError("specified query message is not a query")
- factory = _message_factory_from_opcode(query.opcode())
+ opcode = query.opcode()
+ factory = _message_factory_from_opcode(opcode)
response = factory(id=query.id)
response.flags = dns.flags.QR | (query.flags & dns.flags.RD)
if recursion_available:
response.flags |= dns.flags.RA
- response.set_opcode(query.opcode())
- response.question = list(query.question)
+ response.set_opcode(opcode)
+ if copy_mode is None:
+ copy_mode = CopyMode.QUESTION
+ if copy_mode != CopyMode.NOTHING:
+ response.question = list(query.question)
+ if copy_mode == CopyMode.EVERYTHING:
+ response.answer = list(query.answer)
+ response.authority = list(query.authority)
+ response.additional = list(query.additional)
if query.edns >= 0:
if pad is None:
# Set response padding per RFC 8467
diff --git a/lib/dns/name.py b/lib/dns/name.py
index 22ccb392..f79f0d0f 100644
--- a/lib/dns/name.py
+++ b/lib/dns/name.py
@@ -59,11 +59,11 @@ class NameRelation(dns.enum.IntEnum):
@classmethod
def _maximum(cls):
- return cls.COMMONANCESTOR
+ return cls.COMMONANCESTOR # pragma: no cover
@classmethod
def _short_name(cls):
- return cls.__name__
+ return cls.__name__ # pragma: no cover
# Backwards compatibility
@@ -277,6 +277,7 @@ class IDNA2008Codec(IDNACodec):
raise NoIDNA2008
try:
if self.uts_46:
+ # pylint: disable=possibly-used-before-assignment
label = idna.uts46_remap(label, False, self.transitional)
return idna.alabel(label)
except idna.IDNAError as e:
diff --git a/lib/dns/nameserver.py b/lib/dns/nameserver.py
index 5dbb4e8b..b02a239b 100644
--- a/lib/dns/nameserver.py
+++ b/lib/dns/nameserver.py
@@ -168,12 +168,14 @@ class DoHNameserver(Nameserver):
bootstrap_address: Optional[str] = None,
verify: Union[bool, str] = True,
want_get: bool = False,
+ http_version: dns.query.HTTPVersion = dns.query.HTTPVersion.DEFAULT,
):
super().__init__()
self.url = url
self.bootstrap_address = bootstrap_address
self.verify = verify
self.want_get = want_get
+ self.http_version = http_version
def kind(self):
return "DoH"
@@ -214,6 +216,7 @@ class DoHNameserver(Nameserver):
ignore_trailing=ignore_trailing,
verify=self.verify,
post=(not self.want_get),
+ http_version=self.http_version,
)
async def async_query(
@@ -238,6 +241,7 @@ class DoHNameserver(Nameserver):
ignore_trailing=ignore_trailing,
verify=self.verify,
post=(not self.want_get),
+ http_version=self.http_version,
)
diff --git a/lib/dns/query.py b/lib/dns/query.py
index f0ee9161..0d8a977a 100644
--- a/lib/dns/query.py
+++ b/lib/dns/query.py
@@ -23,11 +23,13 @@ import enum
import errno
import os
import os.path
+import random
import selectors
import socket
import struct
import time
-from typing import Any, Dict, Optional, Tuple, Union
+import urllib.parse
+from typing import Any, Dict, Optional, Tuple, Union, cast
import dns._features
import dns.exception
@@ -129,7 +131,7 @@ if _have_httpx:
family=socket.AF_UNSPEC,
**kwargs,
):
- if resolver is None:
+ if resolver is None and bootstrap_address is None:
# pylint: disable=import-outside-toplevel,redefined-outer-name
import dns.resolver
@@ -217,7 +219,7 @@ def _wait_for(fd, readable, writable, _, expiration):
if readable and isinstance(fd, ssl.SSLSocket) and fd.pending() > 0:
return True
- sel = _selector_class()
+ sel = selectors.DefaultSelector()
events = 0
if readable:
events |= selectors.EVENT_READ
@@ -235,26 +237,6 @@ def _wait_for(fd, readable, writable, _, expiration):
raise dns.exception.Timeout
-def _set_selector_class(selector_class):
- # Internal API. Do not use.
-
- global _selector_class
-
- _selector_class = selector_class
-
-
-if hasattr(selectors, "PollSelector"):
- # Prefer poll() on platforms that support it because it has no
- # limits on the maximum value of a file descriptor (plus it will
- # be more efficient for high values).
- #
- # We ignore typing here as we can't say _selector_class is Any
- # on python < 3.8 due to a bug.
- _selector_class = selectors.PollSelector # type: ignore
-else:
- _selector_class = selectors.SelectSelector # type: ignore
-
-
def _wait_for_readable(s, expiration):
_wait_for(s, True, False, True, expiration)
@@ -355,6 +337,36 @@ def _make_socket(af, type, source, ssl_context=None, server_hostname=None):
raise
+def _maybe_get_resolver(
+ resolver: Optional["dns.resolver.Resolver"],
+) -> "dns.resolver.Resolver":
+ # We need a separate method for this to avoid overriding the global
+ # variable "dns" with the as-yet undefined local variable "dns"
+ # in https().
+ if resolver is None:
+ # pylint: disable=import-outside-toplevel,redefined-outer-name
+ import dns.resolver
+
+ resolver = dns.resolver.Resolver()
+ return resolver
+
+
+class HTTPVersion(enum.IntEnum):
+ """Which version of HTTP should be used?
+
+ DEFAULT will select the first version from the list [2, 1.1, 3] that
+ is available.
+ """
+
+ DEFAULT = 0
+ HTTP_1 = 1
+ H1 = 1
+ HTTP_2 = 2
+ H2 = 2
+ HTTP_3 = 3
+ H3 = 3
+
+
def https(
q: dns.message.Message,
where: str,
@@ -370,7 +382,8 @@ def https(
bootstrap_address: Optional[str] = None,
verify: Union[bool, str] = True,
resolver: Optional["dns.resolver.Resolver"] = None,
- family: Optional[int] = socket.AF_UNSPEC,
+ family: int = socket.AF_UNSPEC,
+ http_version: HTTPVersion = HTTPVersion.DEFAULT,
) -> dns.message.Message:
"""Return the response obtained after sending a query via DNS-over-HTTPS.
@@ -420,27 +433,66 @@ def https(
*family*, an ``int``, the address family. If socket.AF_UNSPEC (the default), both A
and AAAA records will be retrieved.
+ *http_version*, a ``dns.query.HTTPVersion``, indicating which HTTP version to use.
+
Returns a ``dns.message.Message``.
"""
+ (af, _, the_source) = _destination_and_source(
+ where, port, source, source_port, False
+ )
+ if af is not None and dns.inet.is_address(where):
+ if af == socket.AF_INET:
+ url = f"https://{where}:{port}{path}"
+ elif af == socket.AF_INET6:
+ url = f"https://[{where}]:{port}{path}"
+ else:
+ url = where
+
+ extensions = {}
+ if bootstrap_address is None:
+ # pylint: disable=possibly-used-before-assignment
+ parsed = urllib.parse.urlparse(url)
+ if parsed.hostname is None:
+ raise ValueError("no hostname in URL")
+ if dns.inet.is_address(parsed.hostname):
+ bootstrap_address = parsed.hostname
+ extensions["sni_hostname"] = parsed.hostname
+ if parsed.port is not None:
+ port = parsed.port
+
+ if http_version == HTTPVersion.H3 or (
+ http_version == HTTPVersion.DEFAULT and not have_doh
+ ):
+ if bootstrap_address is None:
+ resolver = _maybe_get_resolver(resolver)
+ assert parsed.hostname is not None # for mypy
+ answers = resolver.resolve_name(parsed.hostname, family)
+ bootstrap_address = random.choice(list(answers.addresses()))
+ return _http3(
+ q,
+ bootstrap_address,
+ url,
+ timeout,
+ port,
+ source,
+ source_port,
+ one_rr_per_rrset,
+ ignore_trailing,
+ verify=verify,
+ post=post,
+ )
+
if not have_doh:
raise NoDOH # pragma: no cover
if session and not isinstance(session, httpx.Client):
raise ValueError("session parameter must be an httpx.Client")
wire = q.to_wire()
- (af, _, the_source) = _destination_and_source(
- where, port, source, source_port, False
- )
- transport = None
headers = {"accept": "application/dns-message"}
- if af is not None and dns.inet.is_address(where):
- if af == socket.AF_INET:
- url = "https://{}:{}{}".format(where, port, path)
- elif af == socket.AF_INET6:
- url = "https://[{}]:{}{}".format(where, port, path)
- else:
- url = where
+
+ h1 = http_version in (HTTPVersion.H1, HTTPVersion.DEFAULT)
+ h2 = http_version in (HTTPVersion.H2, HTTPVersion.DEFAULT)
# set source port and source address
@@ -450,21 +502,22 @@ def https(
else:
local_address = the_source[0]
local_port = the_source[1]
- transport = _HTTPTransport(
- local_address=local_address,
- http1=True,
- http2=True,
- verify=verify,
- local_port=local_port,
- bootstrap_address=bootstrap_address,
- resolver=resolver,
- family=family,
- )
if session:
cm: contextlib.AbstractContextManager = contextlib.nullcontext(session)
else:
- cm = httpx.Client(http1=True, http2=True, verify=verify, transport=transport)
+ transport = _HTTPTransport(
+ local_address=local_address,
+ http1=h1,
+ http2=h2,
+ verify=verify,
+ local_port=local_port,
+ bootstrap_address=bootstrap_address,
+ resolver=resolver,
+ family=family,
+ )
+
+ cm = httpx.Client(http1=h1, http2=h2, verify=verify, transport=transport)
with cm as session:
# see https://tools.ietf.org/html/rfc8484#section-4.1.1 for DoH
# GET and POST examples
@@ -475,20 +528,30 @@ def https(
"content-length": str(len(wire)),
}
)
- response = session.post(url, headers=headers, content=wire, timeout=timeout)
+ response = session.post(
+ url,
+ headers=headers,
+ content=wire,
+ timeout=timeout,
+ extensions=extensions,
+ )
else:
wire = base64.urlsafe_b64encode(wire).rstrip(b"=")
twire = wire.decode() # httpx does a repr() if we give it bytes
response = session.get(
- url, headers=headers, timeout=timeout, params={"dns": twire}
+ url,
+ headers=headers,
+ timeout=timeout,
+ params={"dns": twire},
+ extensions=extensions,
)
# see https://tools.ietf.org/html/rfc8484#section-4.2.1 for info about DoH
# status codes
if response.status_code < 200 or response.status_code > 299:
raise ValueError(
- "{} responded with status code {}"
- "\nResponse body: {}".format(where, response.status_code, response.content)
+ f"{where} responded with status code {response.status_code}"
+ f"\nResponse body: {response.content}"
)
r = dns.message.from_wire(
response.content,
@@ -503,6 +566,81 @@ def https(
return r
+def _find_header(headers: dns.quic.Headers, name: bytes) -> bytes:
+ if headers is None:
+ raise KeyError
+ for header, value in headers:
+ if header == name:
+ return value
+ raise KeyError
+
+
+def _check_status(headers: dns.quic.Headers, peer: str, wire: bytes) -> None:
+ value = _find_header(headers, b":status")
+ if value is None:
+ raise SyntaxError("no :status header in response")
+ status = int(value)
+ if status < 0:
+ raise SyntaxError("status is negative")
+ if status < 200 or status > 299:
+ error = ""
+ if len(wire) > 0:
+ try:
+ error = ": " + wire.decode()
+ except Exception:
+ pass
+ raise ValueError(f"{peer} responded with status code {status}{error}")
+
+
+def _http3(
+ q: dns.message.Message,
+ where: str,
+ url: str,
+ timeout: Optional[float] = None,
+ port: int = 853,
+ source: Optional[str] = None,
+ source_port: int = 0,
+ one_rr_per_rrset: bool = False,
+ ignore_trailing: bool = False,
+ verify: Union[bool, str] = True,
+ hostname: Optional[str] = None,
+ post: bool = True,
+) -> dns.message.Message:
+ if not dns.quic.have_quic:
+ raise NoDOH("DNS-over-HTTP3 is not available.") # pragma: no cover
+
+ url_parts = urllib.parse.urlparse(url)
+ hostname = url_parts.hostname
+ if url_parts.port is not None:
+ port = url_parts.port
+
+ q.id = 0
+ wire = q.to_wire()
+ manager = dns.quic.SyncQuicManager(
+ verify_mode=verify, server_name=hostname, h3=True
+ )
+
+ with manager:
+ connection = manager.connect(where, port, source, source_port)
+ (start, expiration) = _compute_times(timeout)
+ with connection.make_stream(timeout) as stream:
+ stream.send_h3(url, wire, post)
+ wire = stream.receive(_remaining(expiration))
+ _check_status(stream.headers(), where, wire)
+ finish = time.time()
+ r = dns.message.from_wire(
+ wire,
+ keyring=q.keyring,
+ request_mac=q.request_mac,
+ one_rr_per_rrset=one_rr_per_rrset,
+ ignore_trailing=ignore_trailing,
+ )
+ r.time = max(finish - start, 0.0)
+ if not q.is_response(r):
+ raise BadResponse
+ return r
+
+
def _udp_recv(sock, max_size, expiration):
"""Reads a datagram from the socket.
A Timeout exception will be raised if the operation is not completed
@@ -855,7 +993,7 @@ def _net_read(sock, count, expiration):
try:
n = sock.recv(count)
if n == b"":
- raise EOFError
+ raise EOFError("EOF")
count -= len(n)
s += n
except (BlockingIOError, ssl.SSLWantReadError):
@@ -1023,6 +1161,7 @@ def tcp(
cm = _make_socket(af, socket.SOCK_STREAM, source)
with cm as s:
if not sock:
+ # pylint: disable=possibly-used-before-assignment
_connect(s, destination, expiration)
send_tcp(s, wire, expiration)
(r, received_time) = receive_tcp(
@@ -1188,6 +1327,7 @@ def quic(
ignore_trailing: bool = False,
connection: Optional[dns.quic.SyncQuicConnection] = None,
verify: Union[bool, str] = True,
+ hostname: Optional[str] = None,
server_hostname: Optional[str] = None,
) -> dns.message.Message:
"""Return the response obtained after sending a query via DNS-over-QUIC.
@@ -1212,17 +1352,21 @@ def quic(
*ignore_trailing*, a ``bool``. If ``True``, ignore trailing junk at end of the
received message.
- *connection*, a ``dns.quic.SyncQuicConnection``. If provided, the
- connection to use to send the query.
+ *connection*, a ``dns.quic.SyncQuicConnection``. If provided, the connection to use
+ to send the query.
*verify*, a ``bool`` or ``str``. If a ``True``, then TLS certificate verification
of the server is done using the default CA bundle; if ``False``, then no
verification is done; if a `str` then it specifies the path to a certificate file or
directory which will be used for verification.
- *server_hostname*, a ``str`` containing the server's hostname. The
- default is ``None``, which means that no hostname is known, and if an
- SSL context is created, hostname checking will be disabled.
+ *hostname*, a ``str`` containing the server's hostname or ``None``. The default is
+ ``None``, which means that no hostname is known, and if an SSL context is created,
+ hostname checking will be disabled. This value is ignored if *url* is not
+ ``None``.
+
+ *server_hostname*, a ``str`` or ``None``. This item is for backwards compatibility
+ only, and has the same meaning as *hostname*.
Returns a ``dns.message.Message``.
"""
@@ -1230,6 +1374,9 @@ def quic(
if not dns.quic.have_quic:
raise NoDOQ("DNS-over-QUIC is not available.") # pragma: no cover
+ if server_hostname is not None and hostname is None:
+ hostname = server_hostname
+
q.id = 0
wire = q.to_wire()
the_connection: dns.quic.SyncQuicConnection
@@ -1238,9 +1385,7 @@ def quic(
manager: contextlib.AbstractContextManager = contextlib.nullcontext(None)
the_connection = connection
else:
- manager = dns.quic.SyncQuicManager(
- verify_mode=verify, server_name=server_hostname
- )
+ manager = dns.quic.SyncQuicManager(verify_mode=verify, server_name=hostname)
the_manager = manager # for type checking happiness
with manager:
@@ -1264,6 +1409,70 @@ def quic(
return r
+class UDPMode(enum.IntEnum):
+ """How should UDP be used in an IXFR from :py:func:`inbound_xfr()`?
+
+ NEVER means "never use UDP; always use TCP"
+ TRY_FIRST means "try to use UDP but fall back to TCP if needed"
+ ONLY means "raise ``dns.xfr.UseTCP`` if trying UDP does not succeed"
+ """
+
+ NEVER = 0
+ TRY_FIRST = 1
+ ONLY = 2
+
+
+def _inbound_xfr(
+ txn_manager: dns.transaction.TransactionManager,
+ s: socket.socket,
+ query: dns.message.Message,
+ serial: Optional[int],
+ timeout: Optional[float],
+ expiration: float,
+) -> Any:
+ """Given a socket, does the zone transfer."""
+ rdtype = query.question[0].rdtype
+ is_ixfr = rdtype == dns.rdatatype.IXFR
+ origin = txn_manager.from_wire_origin()
+ wire = query.to_wire()
+ is_udp = s.type == socket.SOCK_DGRAM
+ if is_udp:
+ _udp_send(s, wire, None, expiration)
+ else:
+ tcpmsg = struct.pack("!H", len(wire)) + wire
+ _net_write(s, tcpmsg, expiration)
+ with dns.xfr.Inbound(txn_manager, rdtype, serial, is_udp) as inbound:
+ done = False
+ tsig_ctx = None
+ while not done:
+ (_, mexpiration) = _compute_times(timeout)
+ if mexpiration is None or (
+ expiration is not None and mexpiration > expiration
+ ):
+ mexpiration = expiration
+ if is_udp:
+ (rwire, _) = _udp_recv(s, 65535, mexpiration)
+ else:
+ ldata = _net_read(s, 2, mexpiration)
+ (l,) = struct.unpack("!H", ldata)
+ rwire = _net_read(s, l, mexpiration)
+ r = dns.message.from_wire(
+ rwire,
+ keyring=query.keyring,
+ request_mac=query.mac,
+ xfr=True,
+ origin=origin,
+ tsig_ctx=tsig_ctx,
+ multi=(not is_udp),
+ one_rr_per_rrset=is_ixfr,
+ )
+ done = inbound.process_message(r)
+ yield r
+ tsig_ctx = r.tsig_ctx
+ if query.keyring and not r.had_tsig:
+ raise dns.exception.FormError("missing TSIG")
+
+
def xfr(
where: str,
zone: Union[dns.name.Name, str],
@@ -1333,134 +1542,52 @@ def xfr(
Returns a generator of ``dns.message.Message`` objects.
"""
+ class DummyTransactionManager(dns.transaction.TransactionManager):
+ def __init__(self, origin, relativize):
+ self.info = (origin, relativize, dns.name.empty if relativize else origin)
+
+ def origin_information(self):
+ return self.info
+
+ def get_class(self) -> dns.rdataclass.RdataClass:
+ raise NotImplementedError # pragma: no cover
+
+ def reader(self):
+ raise NotImplementedError # pragma: no cover
+
+ def writer(self, replacement: bool = False) -> dns.transaction.Transaction:
+ class DummyTransaction:
+ def nop(self, *args, **kw):
+ pass
+
+ def __getattr__(self, _):
+ return self.nop
+
+ return cast(dns.transaction.Transaction, DummyTransaction())
+
if isinstance(zone, str):
zone = dns.name.from_text(zone)
rdtype = dns.rdatatype.RdataType.make(rdtype)
q = dns.message.make_query(zone, rdtype, rdclass)
if rdtype == dns.rdatatype.IXFR:
- rrset = dns.rrset.from_text(zone, 0, "IN", "SOA", ". . %u 0 0 0 0" % serial)
- q.authority.append(rrset)
+ rrset = q.find_rrset(
+ q.authority, zone, dns.rdataclass.IN, dns.rdatatype.SOA, create=True
+ )
+ soa = dns.rdata.from_text("IN", "SOA", ". . %u 0 0 0 0" % serial)
+ rrset.add(soa, 0)
if keyring is not None:
q.use_tsig(keyring, keyname, algorithm=keyalgorithm)
- wire = q.to_wire()
(af, destination, source) = _destination_and_source(
where, port, source, source_port
)
+ (_, expiration) = _compute_times(lifetime)
+ tm = DummyTransactionManager(zone, relativize)
if use_udp and rdtype != dns.rdatatype.IXFR:
raise ValueError("cannot do a UDP AXFR")
sock_type = socket.SOCK_DGRAM if use_udp else socket.SOCK_STREAM
with _make_socket(af, sock_type, source) as s:
- (_, expiration) = _compute_times(lifetime)
_connect(s, destination, expiration)
- l = len(wire)
- if use_udp:
- _udp_send(s, wire, None, expiration)
- else:
- tcpmsg = struct.pack("!H", l) + wire
- _net_write(s, tcpmsg, expiration)
- done = False
- delete_mode = True
- expecting_SOA = False
- soa_rrset = None
- if relativize:
- origin = zone
- oname = dns.name.empty
- else:
- origin = None
- oname = zone
- tsig_ctx = None
- while not done:
- (_, mexpiration) = _compute_times(timeout)
- if mexpiration is None or (
- expiration is not None and mexpiration > expiration
- ):
- mexpiration = expiration
- if use_udp:
- (wire, _) = _udp_recv(s, 65535, mexpiration)
- else:
- ldata = _net_read(s, 2, mexpiration)
- (l,) = struct.unpack("!H", ldata)
- wire = _net_read(s, l, mexpiration)
- is_ixfr = rdtype == dns.rdatatype.IXFR
- r = dns.message.from_wire(
- wire,
- keyring=q.keyring,
- request_mac=q.mac,
- xfr=True,
- origin=origin,
- tsig_ctx=tsig_ctx,
- multi=True,
- one_rr_per_rrset=is_ixfr,
- )
- rcode = r.rcode()
- if rcode != dns.rcode.NOERROR:
- raise TransferError(rcode)
- tsig_ctx = r.tsig_ctx
- answer_index = 0
- if soa_rrset is None:
- if not r.answer or r.answer[0].name != oname:
- raise dns.exception.FormError("No answer or RRset not for qname")
- rrset = r.answer[0]
- if rrset.rdtype != dns.rdatatype.SOA:
- raise dns.exception.FormError("first RRset is not an SOA")
- answer_index = 1
- soa_rrset = rrset.copy()
- if rdtype == dns.rdatatype.IXFR:
- if dns.serial.Serial(soa_rrset[0].serial) <= serial:
- #
- # We're already up-to-date.
- #
- done = True
- else:
- expecting_SOA = True
- #
- # Process SOAs in the answer section (other than the initial
- # SOA in the first message).
- #
- for rrset in r.answer[answer_index:]:
- if done:
- raise dns.exception.FormError("answers after final SOA")
- if rrset.rdtype == dns.rdatatype.SOA and rrset.name == oname:
- if expecting_SOA:
- if rrset[0].serial != serial:
- raise dns.exception.FormError("IXFR base serial mismatch")
- expecting_SOA = False
- elif rdtype == dns.rdatatype.IXFR:
- delete_mode = not delete_mode
- #
- # If this SOA RRset is equal to the first we saw then we're
- # finished. If this is an IXFR we also check that we're
- # seeing the record in the expected part of the response.
- #
- if rrset == soa_rrset and (
- rdtype == dns.rdatatype.AXFR
- or (rdtype == dns.rdatatype.IXFR and delete_mode)
- ):
- done = True
- elif expecting_SOA:
- #
- # We made an IXFR request and are expecting another
- # SOA RR, but saw something else, so this must be an
- # AXFR response.
- #
- rdtype = dns.rdatatype.AXFR
- expecting_SOA = False
- if done and q.keyring and not r.had_tsig:
- raise dns.exception.FormError("missing TSIG")
- yield r
-
-
-class UDPMode(enum.IntEnum):
- """How should UDP be used in an IXFR from :py:func:`inbound_xfr()`?
-
- NEVER means "never use UDP; always use TCP"
- TRY_FIRST means "try to use UDP but fall back to TCP if needed"
- ONLY means "raise ``dns.xfr.UseTCP`` if trying UDP does not succeed"
- """
-
- NEVER = 0
- TRY_FIRST = 1
- ONLY = 2
+ yield from _inbound_xfr(tm, s, q, serial, timeout, expiration)
def inbound_xfr(
@@ -1514,65 +1641,25 @@ def inbound_xfr(
(query, serial) = dns.xfr.make_query(txn_manager)
else:
serial = dns.xfr.extract_serial_from_query(query)
- rdtype = query.question[0].rdtype
- is_ixfr = rdtype == dns.rdatatype.IXFR
- origin = txn_manager.from_wire_origin()
- wire = query.to_wire()
+
(af, destination, source) = _destination_and_source(
where, port, source, source_port
)
(_, expiration) = _compute_times(lifetime)
- retry = True
- while retry:
- retry = False
- if is_ixfr and udp_mode != UDPMode.NEVER:
- sock_type = socket.SOCK_DGRAM
- is_udp = True
- else:
- sock_type = socket.SOCK_STREAM
- is_udp = False
- with _make_socket(af, sock_type, source) as s:
+ if query.question[0].rdtype == dns.rdatatype.IXFR and udp_mode != UDPMode.NEVER:
+ with _make_socket(af, socket.SOCK_DGRAM, source) as s:
_connect(s, destination, expiration)
- if is_udp:
- _udp_send(s, wire, None, expiration)
- else:
- tcpmsg = struct.pack("!H", len(wire)) + wire
- _net_write(s, tcpmsg, expiration)
- with dns.xfr.Inbound(txn_manager, rdtype, serial, is_udp) as inbound:
- done = False
- tsig_ctx = None
- while not done:
- (_, mexpiration) = _compute_times(timeout)
- if mexpiration is None or (
- expiration is not None and mexpiration > expiration
- ):
- mexpiration = expiration
- if is_udp:
- (rwire, _) = _udp_recv(s, 65535, mexpiration)
- else:
- ldata = _net_read(s, 2, mexpiration)
- (l,) = struct.unpack("!H", ldata)
- rwire = _net_read(s, l, mexpiration)
- r = dns.message.from_wire(
- rwire,
- keyring=query.keyring,
- request_mac=query.mac,
- xfr=True,
- origin=origin,
- tsig_ctx=tsig_ctx,
- multi=(not is_udp),
- one_rr_per_rrset=is_ixfr,
- )
- try:
- done = inbound.process_message(r)
- except dns.xfr.UseTCP:
- assert is_udp # should not happen if we used TCP!
- if udp_mode == UDPMode.ONLY:
- raise
- done = True
- retry = True
- udp_mode = UDPMode.NEVER
- continue
- tsig_ctx = r.tsig_ctx
- if not retry and query.keyring and not r.had_tsig:
- raise dns.exception.FormError("missing TSIG")
+ try:
+ for _ in _inbound_xfr(
+ txn_manager, s, query, serial, timeout, expiration
+ ):
+ pass
+ return
+ except dns.xfr.UseTCP:
+ if udp_mode == UDPMode.ONLY:
+ raise
+
+ with _make_socket(af, socket.SOCK_STREAM, source) as s:
+ _connect(s, destination, expiration)
+ for _ in _inbound_xfr(txn_manager, s, query, serial, timeout, expiration):
+ pass
diff --git a/lib/dns/quic/__init__.py b/lib/dns/quic/__init__.py
index 20aff345..0750e729 100644
--- a/lib/dns/quic/__init__.py
+++ b/lib/dns/quic/__init__.py
@@ -1,5 +1,7 @@
# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
+from typing import List, Tuple
+
import dns._features
import dns.asyncbackend
@@ -73,3 +75,6 @@ else: # pragma: no cover
class SyncQuicConnection: # type: ignore
def make_stream(self) -> Any:
raise NotImplementedError
+
+
+Headers = List[Tuple[bytes, bytes]]
diff --git a/lib/dns/quic/_asyncio.py b/lib/dns/quic/_asyncio.py
index 0f44331f..f87515da 100644
--- a/lib/dns/quic/_asyncio.py
+++ b/lib/dns/quic/_asyncio.py
@@ -43,12 +43,26 @@ class AsyncioQuicStream(BaseQuicStream):
raise dns.exception.Timeout
self._expecting = 0
+ async def wait_for_end(self, expiration):
+ while True:
+ timeout = self._timeout_from_expiration(expiration)
+ if self._buffer.seen_end():
+ return
+ try:
+ await asyncio.wait_for(self._wait_for_wake_up(), timeout)
+ except TimeoutError:
+ raise dns.exception.Timeout
+
async def receive(self, timeout=None):
expiration = self._expiration_from_timeout(timeout)
- await self.wait_for(2, expiration)
- (size,) = struct.unpack("!H", self._buffer.get(2))
- await self.wait_for(size, expiration)
- return self._buffer.get(size)
+ if self._connection.is_h3():
+ await self.wait_for_end(expiration)
+ return self._buffer.get_all()
+ else:
+ await self.wait_for(2, expiration)
+ (size,) = struct.unpack("!H", self._buffer.get(2))
+ await self.wait_for(size, expiration)
+ return self._buffer.get(size)
async def send(self, datagram, is_end=False):
data = self._encapsulate(datagram)
@@ -83,6 +97,7 @@ class AsyncioQuicConnection(AsyncQuicConnection):
self._wake_timer = asyncio.Condition()
self._receiver_task = None
self._sender_task = None
+ self._wake_pending = False
async def _receiver(self):
try:
@@ -104,19 +119,24 @@ class AsyncioQuicConnection(AsyncQuicConnection):
self._connection.receive_datagram(datagram, address, time.time())
# Wake up the timer in case the sender is sleeping, as there may be
# stuff to send now.
- async with self._wake_timer:
- self._wake_timer.notify_all()
+ await self._wakeup()
except Exception:
pass
finally:
self._done = True
- async with self._wake_timer:
- self._wake_timer.notify_all()
+ await self._wakeup()
self._handshake_complete.set()
+ async def _wakeup(self):
+ self._wake_pending = True
+ async with self._wake_timer:
+ self._wake_timer.notify_all()
+
async def _wait_for_wake_timer(self):
async with self._wake_timer:
- await self._wake_timer.wait()
+ if not self._wake_pending:
+ await self._wake_timer.wait()
+ self._wake_pending = False
async def _sender(self):
await self._socket_created.wait()
@@ -140,9 +160,28 @@ class AsyncioQuicConnection(AsyncQuicConnection):
if event is None:
return
if isinstance(event, aioquic.quic.events.StreamDataReceived):
- stream = self._streams.get(event.stream_id)
- if stream:
- await stream._add_input(event.data, event.end_stream)
+ if self.is_h3():
+ h3_events = self._h3_conn.handle_event(event)
+ for h3_event in h3_events:
+ if isinstance(h3_event, aioquic.h3.events.HeadersReceived):
+ stream = self._streams.get(event.stream_id)
+ if stream:
+ if stream._headers is None:
+ stream._headers = h3_event.headers
+ elif stream._trailers is None:
+ stream._trailers = h3_event.headers
+ if h3_event.stream_ended:
+ await stream._add_input(b"", True)
+ elif isinstance(h3_event, aioquic.h3.events.DataReceived):
+ stream = self._streams.get(event.stream_id)
+ if stream:
+ await stream._add_input(
+ h3_event.data, h3_event.stream_ended
+ )
+ else:
+ stream = self._streams.get(event.stream_id)
+ if stream:
+ await stream._add_input(event.data, event.end_stream)
elif isinstance(event, aioquic.quic.events.HandshakeCompleted):
self._handshake_complete.set()
elif isinstance(event, aioquic.quic.events.ConnectionTerminated):
@@ -161,8 +200,7 @@ class AsyncioQuicConnection(AsyncQuicConnection):
async def write(self, stream, data, is_end=False):
self._connection.send_stream_data(stream, data, is_end)
- async with self._wake_timer:
- self._wake_timer.notify_all()
+ await self._wakeup()
def run(self):
if self._closed:
@@ -189,8 +227,7 @@ class AsyncioQuicConnection(AsyncQuicConnection):
self._connection.close()
# sender might be blocked on this, so set it
self._socket_created.set()
- async with self._wake_timer:
- self._wake_timer.notify_all()
+ await self._wakeup()
try:
await self._receiver_task
except asyncio.CancelledError:
@@ -203,8 +240,10 @@ class AsyncioQuicConnection(AsyncQuicConnection):
class AsyncioQuicManager(AsyncQuicManager):
- def __init__(self, conf=None, verify_mode=ssl.CERT_REQUIRED, server_name=None):
- super().__init__(conf, verify_mode, AsyncioQuicConnection, server_name)
+ def __init__(
+ self, conf=None, verify_mode=ssl.CERT_REQUIRED, server_name=None, h3=False
+ ):
+ super().__init__(conf, verify_mode, AsyncioQuicConnection, server_name, h3)
def connect(
self, address, port=853, source=None, source_port=0, want_session_ticket=True
diff --git a/lib/dns/quic/_common.py b/lib/dns/quic/_common.py
index 0eacc691..ce575b03 100644
--- a/lib/dns/quic/_common.py
+++ b/lib/dns/quic/_common.py
@@ -1,12 +1,16 @@
# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
+import base64
import copy
import functools
import socket
import struct
import time
+import urllib
from typing import Any, Optional
+import aioquic.h3.connection # type: ignore
+import aioquic.h3.events # type: ignore
import aioquic.quic.configuration # type: ignore
import aioquic.quic.connection # type: ignore
@@ -51,6 +55,12 @@ class Buffer:
self._buffer = self._buffer[amount:]
return data
+ def get_all(self):
+ assert self.seen_end()
+ data = self._buffer
+ self._buffer = b""
+ return data
+
class BaseQuicStream:
def __init__(self, connection, stream_id):
@@ -58,10 +68,18 @@ class BaseQuicStream:
self._stream_id = stream_id
self._buffer = Buffer()
self._expecting = 0
+ self._headers = None
+ self._trailers = None
def id(self):
return self._stream_id
+ def headers(self):
+ return self._headers
+
+ def trailers(self):
+ return self._trailers
+
def _expiration_from_timeout(self, timeout):
if timeout is not None:
expiration = time.time() + timeout
@@ -77,16 +95,51 @@ class BaseQuicStream:
return timeout
# Subclass must implement receive() as sync / async and which returns a message
- # or raises UnexpectedEOF.
+ # or raises.
+
+ # Subclass must implement send() as sync / async and which takes a message and
+ # an EOF indicator.
+
+ def send_h3(self, url, datagram, post=True):
+ if not self._connection.is_h3():
+ raise SyntaxError("cannot send H3 to a non-H3 connection")
+ url_parts = urllib.parse.urlparse(url)
+ path = url_parts.path.encode()
+ if post:
+ method = b"POST"
+ else:
+ method = b"GET"
+ path += b"?dns=" + base64.urlsafe_b64encode(datagram).rstrip(b"=")
+ headers = [
+ (b":method", method),
+ (b":scheme", url_parts.scheme.encode()),
+ (b":authority", url_parts.netloc.encode()),
+ (b":path", path),
+ (b"accept", b"application/dns-message"),
+ ]
+ if post:
+ headers.extend(
+ [
+ (b"content-type", b"application/dns-message"),
+ (b"content-length", str(len(datagram)).encode()),
+ ]
+ )
+ self._connection.send_headers(self._stream_id, headers, not post)
+ if post:
+ self._connection.send_data(self._stream_id, datagram, True)
def _encapsulate(self, datagram):
+ if self._connection.is_h3():
+ return datagram
l = len(datagram)
return struct.pack("!H", l) + datagram
def _common_add_input(self, data, is_end):
self._buffer.put(data, is_end)
try:
- return self._expecting > 0 and self._buffer.have(self._expecting)
+ return (
+ self._expecting > 0 and self._buffer.have(self._expecting)
+ ) or self._buffer.seen_end
except UnexpectedEOF:
return True
@@ -97,7 +150,13 @@ class BaseQuicStream:
class BaseQuicConnection:
def __init__(
- self, connection, address, port, source=None, source_port=0, manager=None
+ self,
+ connection,
+ address,
+ port,
+ source=None,
+ source_port=0,
+ manager=None,
):
self._done = False
self._connection = connection
@@ -106,6 +165,10 @@ class BaseQuicConnection:
self._closed = False
self._manager = manager
self._streams = {}
+ if manager.is_h3():
+ self._h3_conn = aioquic.h3.connection.H3Connection(connection, False)
+ else:
+ self._h3_conn = None
self._af = dns.inet.af_for_address(address)
self._peer = dns.inet.low_level_address_tuple((address, port))
if source is None and source_port != 0:
@@ -120,9 +183,18 @@ class BaseQuicConnection:
else:
self._source = None
+ def is_h3(self):
+ return self._h3_conn is not None
+
def close_stream(self, stream_id):
del self._streams[stream_id]
+ def send_headers(self, stream_id, headers, is_end=False):
+ self._h3_conn.send_headers(stream_id, headers, is_end)
+
+ def send_data(self, stream_id, data, is_end=False):
+ self._h3_conn.send_data(stream_id, data, is_end)
+
def _get_timer_values(self, closed_is_special=True):
now = time.time()
expiration = self._connection.get_timer()
@@ -148,17 +220,25 @@ class AsyncQuicConnection(BaseQuicConnection):
class BaseQuicManager:
- def __init__(self, conf, verify_mode, connection_factory, server_name=None):
+ def __init__(
+ self, conf, verify_mode, connection_factory, server_name=None, h3=False
+ ):
self._connections = {}
self._connection_factory = connection_factory
self._session_tickets = {}
+ self._tokens = {}
+ self._h3 = h3
if conf is None:
verify_path = None
if isinstance(verify_mode, str):
verify_path = verify_mode
verify_mode = True
+ if h3:
+ alpn_protocols = ["h3"]
+ else:
+ alpn_protocols = ["doq", "doq-i03"]
conf = aioquic.quic.configuration.QuicConfiguration(
- alpn_protocols=["doq", "doq-i03"],
+ alpn_protocols=alpn_protocols,
verify_mode=verify_mode,
server_name=server_name,
)
@@ -167,7 +247,13 @@ class BaseQuicManager:
self._conf = conf
def _connect(
- self, address, port=853, source=None, source_port=0, want_session_ticket=True
+ self,
+ address,
+ port=853,
+ source=None,
+ source_port=0,
+ want_session_ticket=True,
+ want_token=True,
):
connection = self._connections.get((address, port))
if connection is not None:
@@ -189,9 +275,24 @@ class BaseQuicManager:
)
else:
session_ticket_handler = None
+ if want_token:
+ try:
+ token = self._tokens.pop((address, port))
+ # We found a token, so make a configuration that uses it.
+ conf = copy.copy(conf)
+ conf.token = token
+ except KeyError:
+ # No token
+ pass
+ # Whether or not we found a token, we want a handler to save # one.
+ token_handler = functools.partial(self.save_token, address, port)
+ else:
+ token_handler = None
+
qconn = aioquic.quic.connection.QuicConnection(
configuration=conf,
session_ticket_handler=session_ticket_handler,
+ token_handler=token_handler,
)
lladdress = dns.inet.low_level_address_tuple((address, port))
qconn.connect(lladdress, time.time())
@@ -207,6 +308,9 @@ class BaseQuicManager:
except KeyError:
pass
+ def is_h3(self):
+ return self._h3
+
def save_session_ticket(self, address, port, ticket):
# We rely on dictionaries keys() being in insertion order here. We
# can't just popitem() as that would be LIFO which is the opposite of
@@ -218,6 +322,17 @@ class BaseQuicManager:
del self._session_tickets[key]
self._session_tickets[(address, port)] = ticket
+ def save_token(self, address, port, token):
+ # We rely on dictionaries keys() being in insertion order here. We
+ # can't just popitem() as that would be LIFO which is the opposite of
+ # what we want.
+ l = len(self._tokens)
+ if l >= MAX_SESSION_TICKETS:
+ keys_to_delete = list(self._tokens.keys())[0:SESSIONS_TO_DELETE]
+ for key in keys_to_delete:
+ del self._tokens[key]
+ self._tokens[(address, port)] = token
+
class AsyncQuicManager(BaseQuicManager):
def connect(self, address, port=853, source=None, source_port=0):
diff --git a/lib/dns/quic/_sync.py b/lib/dns/quic/_sync.py
index 120cb5f3..473d1f48 100644
--- a/lib/dns/quic/_sync.py
+++ b/lib/dns/quic/_sync.py
@@ -21,11 +21,9 @@ from dns.quic._common import (
UnexpectedEOF,
)
-# Avoid circularity with dns.query
-if hasattr(selectors, "PollSelector"):
- _selector_class = selectors.PollSelector # type: ignore
-else:
- _selector_class = selectors.SelectSelector # type: ignore
+# Function used to create a socket. Can be overridden if needed in special
+# situations.
+socket_factory = socket.socket
class SyncQuicStream(BaseQuicStream):
@@ -46,14 +44,29 @@ class SyncQuicStream(BaseQuicStream):
raise dns.exception.Timeout
self._expecting = 0
+ def wait_for_end(self, expiration):
+ while True:
+ timeout = self._timeout_from_expiration(expiration)
+ with self._lock:
+ if self._buffer.seen_end():
+ return
+ with self._wake_up:
+ if not self._wake_up.wait(timeout):
+ raise dns.exception.Timeout
+
def receive(self, timeout=None):
expiration = self._expiration_from_timeout(timeout)
- self.wait_for(2, expiration)
- with self._lock:
- (size,) = struct.unpack("!H", self._buffer.get(2))
- self.wait_for(size, expiration)
- with self._lock:
- return self._buffer.get(size)
+ if self._connection.is_h3():
+ self.wait_for_end(expiration)
+ with self._lock:
+ return self._buffer.get_all()
+ else:
+ self.wait_for(2, expiration)
+ with self._lock:
+ (size,) = struct.unpack("!H", self._buffer.get(2))
+ self.wait_for(size, expiration)
+ with self._lock:
+ return self._buffer.get(size)
def send(self, datagram, is_end=False):
data = self._encapsulate(datagram)
@@ -81,7 +94,7 @@ class SyncQuicStream(BaseQuicStream):
class SyncQuicConnection(BaseQuicConnection):
def __init__(self, connection, address, port, source, source_port, manager):
super().__init__(connection, address, port, source, source_port, manager)
- self._socket = socket.socket(self._af, socket.SOCK_DGRAM, 0)
+ self._socket = socket_factory(self._af, socket.SOCK_DGRAM, 0)
if self._source is not None:
try:
self._socket.bind(
@@ -118,7 +131,7 @@ class SyncQuicConnection(BaseQuicConnection):
def _worker(self):
try:
- sel = _selector_class()
+ sel = selectors.DefaultSelector()
sel.register(self._socket, selectors.EVENT_READ, self._read)
sel.register(self._receive_wakeup, selectors.EVENT_READ, self._drain_wakeup)
while not self._done:
@@ -140,6 +153,7 @@ class SyncQuicConnection(BaseQuicConnection):
finally:
with self._lock:
self._done = True
+ self._socket.close()
# Ensure anyone waiting for this gets woken up.
self._handshake_complete.set()
@@ -150,10 +164,29 @@ class SyncQuicConnection(BaseQuicConnection):
if event is None:
return
if isinstance(event, aioquic.quic.events.StreamDataReceived):
- with self._lock:
- stream = self._streams.get(event.stream_id)
- if stream:
- stream._add_input(event.data, event.end_stream)
+ if self.is_h3():
+ h3_events = self._h3_conn.handle_event(event)
+ for h3_event in h3_events:
+ if isinstance(h3_event, aioquic.h3.events.HeadersReceived):
+ with self._lock:
+ stream = self._streams.get(event.stream_id)
+ if stream:
+ if stream._headers is None:
+ stream._headers = h3_event.headers
+ elif stream._trailers is None:
+ stream._trailers = h3_event.headers
+ if h3_event.stream_ended:
+ stream._add_input(b"", True)
+ elif isinstance(h3_event, aioquic.h3.events.DataReceived):
+ with self._lock:
+ stream = self._streams.get(event.stream_id)
+ if stream:
+ stream._add_input(h3_event.data, h3_event.stream_ended)
+ else:
+ with self._lock:
+ stream = self._streams.get(event.stream_id)
+ if stream:
+ stream._add_input(event.data, event.end_stream)
elif isinstance(event, aioquic.quic.events.HandshakeCompleted):
self._handshake_complete.set()
elif isinstance(event, aioquic.quic.events.ConnectionTerminated):
@@ -170,6 +203,18 @@ class SyncQuicConnection(BaseQuicConnection):
self._connection.send_stream_data(stream, data, is_end)
self._send_wakeup.send(b"\x01")
+ def send_headers(self, stream_id, headers, is_end=False):
+ with self._lock:
+ super().send_headers(stream_id, headers, is_end)
+ if is_end:
+ self._send_wakeup.send(b"\x01")
+
+ def send_data(self, stream_id, data, is_end=False):
+ with self._lock:
+ super().send_data(stream_id, data, is_end)
+ if is_end:
+ self._send_wakeup.send(b"\x01")
+
def run(self):
if self._closed:
return
@@ -203,16 +248,24 @@ class SyncQuicConnection(BaseQuicConnection):
class SyncQuicManager(BaseQuicManager):
- def __init__(self, conf=None, verify_mode=ssl.CERT_REQUIRED, server_name=None):
- super().__init__(conf, verify_mode, SyncQuicConnection, server_name)
+ def __init__(
+ self, conf=None, verify_mode=ssl.CERT_REQUIRED, server_name=None, h3=False
+ ):
+ super().__init__(conf, verify_mode, SyncQuicConnection, server_name, h3)
self._lock = threading.Lock()
def connect(
- self, address, port=853, source=None, source_port=0, want_session_ticket=True
+ self,
+ address,
+ port=853,
+ source=None,
+ source_port=0,
+ want_session_ticket=True,
+ want_token=True,
):
with self._lock:
(connection, start) = self._connect(
- address, port, source, source_port, want_session_ticket
+ address, port, source, source_port, want_session_ticket, want_token
)
if start:
connection.run()
@@ -226,6 +279,10 @@ class SyncQuicManager(BaseQuicManager):
with self._lock:
super().save_session_ticket(address, port, ticket)
+ def save_token(self, address, port, token):
+ with self._lock:
+ super().save_token(address, port, token)
+
def __enter__(self):
return self
diff --git a/lib/dns/quic/_trio.py b/lib/dns/quic/_trio.py
index 35e36b98..ae79f369 100644
--- a/lib/dns/quic/_trio.py
+++ b/lib/dns/quic/_trio.py
@@ -36,16 +36,27 @@ class TrioQuicStream(BaseQuicStream):
await self._wake_up.wait()
self._expecting = 0
+ async def wait_for_end(self):
+ while True:
+ if self._buffer.seen_end():
+ return
+ async with self._wake_up:
+ await self._wake_up.wait()
+
async def receive(self, timeout=None):
if timeout is None:
context = NullContext(None)
else:
context = trio.move_on_after(timeout)
with context:
- await self.wait_for(2)
- (size,) = struct.unpack("!H", self._buffer.get(2))
- await self.wait_for(size)
- return self._buffer.get(size)
+ if self._connection.is_h3():
+ await self.wait_for_end()
+ return self._buffer.get_all()
+ else:
+ await self.wait_for(2)
+ (size,) = struct.unpack("!H", self._buffer.get(2))
+ await self.wait_for(size)
+ return self._buffer.get(size)
raise dns.exception.Timeout
async def send(self, datagram, is_end=False):
@@ -115,6 +126,7 @@ class TrioQuicConnection(AsyncQuicConnection):
await self._socket.send(datagram)
finally:
self._done = True
+ self._socket.close()
self._handshake_complete.set()
async def _handle_events(self):
@@ -124,9 +136,28 @@ class TrioQuicConnection(AsyncQuicConnection):
if event is None:
return
if isinstance(event, aioquic.quic.events.StreamDataReceived):
- stream = self._streams.get(event.stream_id)
- if stream:
- await stream._add_input(event.data, event.end_stream)
+ if self.is_h3():
+ h3_events = self._h3_conn.handle_event(event)
+ for h3_event in h3_events:
+ if isinstance(h3_event, aioquic.h3.events.HeadersReceived):
+ stream = self._streams.get(event.stream_id)
+ if stream:
+ if stream._headers is None:
+ stream._headers = h3_event.headers
+ elif stream._trailers is None:
+ stream._trailers = h3_event.headers
+ if h3_event.stream_ended:
+ await stream._add_input(b"", True)
+ elif isinstance(h3_event, aioquic.h3.events.DataReceived):
+ stream = self._streams.get(event.stream_id)
+ if stream:
+ await stream._add_input(
+ h3_event.data, h3_event.stream_ended
+ )
+ else:
+ stream = self._streams.get(event.stream_id)
+ if stream:
+ await stream._add_input(event.data, event.end_stream)
elif isinstance(event, aioquic.quic.events.HandshakeCompleted):
self._handshake_complete.set()
elif isinstance(event, aioquic.quic.events.ConnectionTerminated):
@@ -183,9 +214,14 @@ class TrioQuicConnection(AsyncQuicConnection):
class TrioQuicManager(AsyncQuicManager):
def __init__(
- self, nursery, conf=None, verify_mode=ssl.CERT_REQUIRED, server_name=None
+ self,
+ nursery,
+ conf=None,
+ verify_mode=ssl.CERT_REQUIRED,
+ server_name=None,
+ h3=False,
):
- super().__init__(conf, verify_mode, TrioQuicConnection, server_name)
+ super().__init__(conf, verify_mode, TrioQuicConnection, server_name, h3)
self._nursery = nursery
def connect(
diff --git a/lib/dns/rdata.py b/lib/dns/rdata.py
index 024fd8f6..8099c26a 100644
--- a/lib/dns/rdata.py
+++ b/lib/dns/rdata.py
@@ -214,7 +214,7 @@ class Rdata:
compress: Optional[dns.name.CompressType] = None,
origin: Optional[dns.name.Name] = None,
canonicalize: bool = False,
- ) -> bytes:
+ ) -> None:
raise NotImplementedError # pragma: no cover
def to_wire(
@@ -223,14 +223,19 @@ class Rdata:
compress: Optional[dns.name.CompressType] = None,
origin: Optional[dns.name.Name] = None,
canonicalize: bool = False,
- ) -> bytes:
+ ) -> Optional[bytes]:
"""Convert an rdata to wire format.
- Returns a ``bytes`` or ``None``.
+ Returns a ``bytes`` if no output file was specified, or ``None`` otherwise.
"""
if file:
- return self._to_wire(file, compress, origin, canonicalize)
+ # We call _to_wire() and then return None explicitly instead of
+ # of just returning the None from _to_wire() as mypy's func-returns-value
+ # unhelpfully errors out with "error: "_to_wire" of "Rdata" does not return
+ # a value (it only ever returns None)"
+ self._to_wire(file, compress, origin, canonicalize)
+ return None
else:
f = io.BytesIO()
self._to_wire(f, compress, origin, canonicalize)
@@ -253,8 +258,9 @@ class Rdata:
Returns a ``bytes``.
"""
-
- return self.to_wire(origin=origin, canonicalize=True)
+ wire = self.to_wire(origin=origin, canonicalize=True)
+ assert wire is not None # for mypy
+ return wire
def __repr__(self):
covers = self.covers()
@@ -434,15 +440,11 @@ class Rdata:
continue
if key not in parameters:
raise AttributeError(
- "'{}' object has no attribute '{}'".format(
- self.__class__.__name__, key
- )
+ f"'{self.__class__.__name__}' object has no attribute '{key}'"
)
if key in ("rdclass", "rdtype"):
raise AttributeError(
- "Cannot overwrite '{}' attribute '{}'".format(
- self.__class__.__name__, key
- )
+ f"Cannot overwrite '{self.__class__.__name__}' attribute '{key}'"
)
# Construct the parameter list. For each field, use the value in
@@ -646,13 +648,14 @@ _rdata_classes: Dict[Tuple[dns.rdataclass.RdataClass, dns.rdatatype.RdataType],
{}
)
_module_prefix = "dns.rdtypes"
+_dynamic_load_allowed = True
-def get_rdata_class(rdclass, rdtype):
+def get_rdata_class(rdclass, rdtype, use_generic=True):
cls = _rdata_classes.get((rdclass, rdtype))
if not cls:
cls = _rdata_classes.get((dns.rdatatype.ANY, rdtype))
- if not cls:
+ if not cls and _dynamic_load_allowed:
rdclass_text = dns.rdataclass.to_text(rdclass)
rdtype_text = dns.rdatatype.to_text(rdtype)
rdtype_text = rdtype_text.replace("-", "_")
@@ -670,12 +673,36 @@ def get_rdata_class(rdclass, rdtype):
_rdata_classes[(rdclass, rdtype)] = cls
except ImportError:
pass
- if not cls:
+ if not cls and use_generic:
cls = GenericRdata
_rdata_classes[(rdclass, rdtype)] = cls
return cls
+def load_all_types(disable_dynamic_load=True):
+ """Load all rdata types for which dnspython has a non-generic implementation.
+
+ Normally dnspython loads DNS rdatatype implementations on demand, but in some
+ specialized cases loading all types at an application-controlled time is preferred.
+
+ If *disable_dynamic_load*, a ``bool``, is ``True`` then dnspython will not attempt
+ to use its dynamic loading mechanism if an unknown type is subsequently encountered,
+ and will simply use the ``GenericRdata`` class.
+ """
+ # Load class IN and ANY types.
+ for rdtype in dns.rdatatype.RdataType:
+ get_rdata_class(dns.rdataclass.IN, rdtype, False)
+ # Load the one non-ANY implementation we have in CH. Everything
+ # else in CH is an ANY type, and we'll discover those on demand but won't
+ # have to import anything.
+ get_rdata_class(dns.rdataclass.CH, dns.rdatatype.A, False)
+ if disable_dynamic_load:
+ # Now disable dynamic loading so any subsequent unknown type immediately becomes
+ # GenericRdata without a load attempt.
+ global _dynamic_load_allowed
+ _dynamic_load_allowed = False
+
+
def from_text(
rdclass: Union[dns.rdataclass.RdataClass, str],
rdtype: Union[dns.rdatatype.RdataType, str],
diff --git a/lib/dns/rdataset.py b/lib/dns/rdataset.py
index 8bff58d7..39cab236 100644
--- a/lib/dns/rdataset.py
+++ b/lib/dns/rdataset.py
@@ -160,7 +160,7 @@ class Rdataset(dns.set.Set):
return s[:100] + "..."
return s
- return "[%s]" % ", ".join("<%s>" % maybe_truncate(str(rr)) for rr in self)
+ return "[" + ", ".join(f"<{maybe_truncate(str(rr))}>" for rr in self) + "]"
def __repr__(self):
if self.covers == 0:
@@ -248,12 +248,8 @@ class Rdataset(dns.set.Set):
# (which is meaningless anyway).
#
s.write(
- "{}{}{} {}\n".format(
- ntext,
- pad,
- dns.rdataclass.to_text(rdclass),
- dns.rdatatype.to_text(self.rdtype),
- )
+ f"{ntext}{pad}{dns.rdataclass.to_text(rdclass)} "
+ f"{dns.rdatatype.to_text(self.rdtype)}\n"
)
else:
for rd in self:
diff --git a/lib/dns/rdatatype.py b/lib/dns/rdatatype.py
index e6c58186..aa9e561c 100644
--- a/lib/dns/rdatatype.py
+++ b/lib/dns/rdatatype.py
@@ -105,6 +105,8 @@ class RdataType(dns.enum.IntEnum):
CAA = 257
AVC = 258
AMTRELAY = 260
+ RESINFO = 261
+ WALLET = 262
TA = 32768
DLV = 32769
@@ -125,7 +127,7 @@ class RdataType(dns.enum.IntEnum):
if text.find("-") >= 0:
try:
return cls[text.replace("-", "_")]
- except KeyError:
+ except KeyError: # pragma: no cover
pass
return _registered_by_text.get(text)
@@ -326,6 +328,8 @@ URI = RdataType.URI
CAA = RdataType.CAA
AVC = RdataType.AVC
AMTRELAY = RdataType.AMTRELAY
+RESINFO = RdataType.RESINFO
+WALLET = RdataType.WALLET
TA = RdataType.TA
DLV = RdataType.DLV
diff --git a/lib/dns/rdtypes/ANY/GPOS.py b/lib/dns/rdtypes/ANY/GPOS.py
index 312338f9..d79f4a06 100644
--- a/lib/dns/rdtypes/ANY/GPOS.py
+++ b/lib/dns/rdtypes/ANY/GPOS.py
@@ -75,8 +75,9 @@ class GPOS(dns.rdata.Rdata):
raise dns.exception.FormError("bad longitude")
def to_text(self, origin=None, relativize=True, **kw):
- return "{} {} {}".format(
- self.latitude.decode(), self.longitude.decode(), self.altitude.decode()
+ return (
+ f"{self.latitude.decode()} {self.longitude.decode()} "
+ f"{self.altitude.decode()}"
)
@classmethod
diff --git a/lib/dns/rdtypes/ANY/HINFO.py b/lib/dns/rdtypes/ANY/HINFO.py
index c2c45de0..06ad3487 100644
--- a/lib/dns/rdtypes/ANY/HINFO.py
+++ b/lib/dns/rdtypes/ANY/HINFO.py
@@ -37,9 +37,7 @@ class HINFO(dns.rdata.Rdata):
self.os = self._as_bytes(os, True, 255)
def to_text(self, origin=None, relativize=True, **kw):
- return '"{}" "{}"'.format(
- dns.rdata._escapify(self.cpu), dns.rdata._escapify(self.os)
- )
+ return f'"{dns.rdata._escapify(self.cpu)}" "{dns.rdata._escapify(self.os)}"'
@classmethod
def from_text(
diff --git a/lib/dns/rdtypes/ANY/HIP.py b/lib/dns/rdtypes/ANY/HIP.py
index 91669139..f3157da7 100644
--- a/lib/dns/rdtypes/ANY/HIP.py
+++ b/lib/dns/rdtypes/ANY/HIP.py
@@ -48,7 +48,7 @@ class HIP(dns.rdata.Rdata):
for server in self.servers:
servers.append(server.choose_relativity(origin, relativize))
if len(servers) > 0:
- text += " " + " ".join((x.to_unicode() for x in servers))
+ text += " " + " ".join(x.to_unicode() for x in servers)
return "%u %s %s%s" % (self.algorithm, hit, key, text)
@classmethod
diff --git a/lib/dns/rdtypes/ANY/ISDN.py b/lib/dns/rdtypes/ANY/ISDN.py
index fb01eab3..6428a0a8 100644
--- a/lib/dns/rdtypes/ANY/ISDN.py
+++ b/lib/dns/rdtypes/ANY/ISDN.py
@@ -38,11 +38,12 @@ class ISDN(dns.rdata.Rdata):
def to_text(self, origin=None, relativize=True, **kw):
if self.subaddress:
- return '"{}" "{}"'.format(
- dns.rdata._escapify(self.address), dns.rdata._escapify(self.subaddress)
+ return (
+ f'"{dns.rdata._escapify(self.address)}" '
+ f'"{dns.rdata._escapify(self.subaddress)}"'
)
else:
- return '"%s"' % dns.rdata._escapify(self.address)
+ return f'"{dns.rdata._escapify(self.address)}"'
@classmethod
def from_text(
diff --git a/lib/dns/rdtypes/ANY/LOC.py b/lib/dns/rdtypes/ANY/LOC.py
index a36a2c10..1153cf03 100644
--- a/lib/dns/rdtypes/ANY/LOC.py
+++ b/lib/dns/rdtypes/ANY/LOC.py
@@ -44,7 +44,7 @@ def _exponent_of(what, desc):
exp = i - 1
break
if exp is None or exp < 0:
- raise dns.exception.SyntaxError("%s value out of bounds" % desc)
+ raise dns.exception.SyntaxError(f"{desc} value out of bounds")
return exp
@@ -83,10 +83,10 @@ def _encode_size(what, desc):
def _decode_size(what, desc):
exponent = what & 0x0F
if exponent > 9:
- raise dns.exception.FormError("bad %s exponent" % desc)
+ raise dns.exception.FormError(f"bad {desc} exponent")
base = (what & 0xF0) >> 4
if base > 9:
- raise dns.exception.FormError("bad %s base" % desc)
+ raise dns.exception.FormError(f"bad {desc} base")
return base * pow(10, exponent)
@@ -184,10 +184,9 @@ class LOC(dns.rdata.Rdata):
or self.horizontal_precision != _default_hprec
or self.vertical_precision != _default_vprec
):
- text += " {:0.2f}m {:0.2f}m {:0.2f}m".format(
- self.size / 100.0,
- self.horizontal_precision / 100.0,
- self.vertical_precision / 100.0,
+ text += (
+ f" {self.size / 100.0:0.2f}m {self.horizontal_precision / 100.0:0.2f}m"
+ f" {self.vertical_precision / 100.0:0.2f}m"
)
return text
diff --git a/lib/dns/rdtypes/ANY/NSEC.py b/lib/dns/rdtypes/ANY/NSEC.py
index 340525a6..3c78b722 100644
--- a/lib/dns/rdtypes/ANY/NSEC.py
+++ b/lib/dns/rdtypes/ANY/NSEC.py
@@ -44,7 +44,7 @@ class NSEC(dns.rdata.Rdata):
def to_text(self, origin=None, relativize=True, **kw):
next = self.next.choose_relativity(origin, relativize)
text = Bitmap(self.windows).to_text()
- return "{}{}".format(next, text)
+ return f"{next}{text}"
@classmethod
def from_text(
diff --git a/lib/dns/rdtypes/ANY/RESINFO.py b/lib/dns/rdtypes/ANY/RESINFO.py
new file mode 100644
index 00000000..76c8ea2a
--- /dev/null
+++ b/lib/dns/rdtypes/ANY/RESINFO.py
@@ -0,0 +1,24 @@
+# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
+
+# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose with or without fee is hereby granted,
+# provided that the above copyright notice and this permission notice
+# appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import dns.immutable
+import dns.rdtypes.txtbase
+
+
+@dns.immutable.immutable
+class RESINFO(dns.rdtypes.txtbase.TXTBase):
+ """RESINFO record"""
diff --git a/lib/dns/rdtypes/ANY/RP.py b/lib/dns/rdtypes/ANY/RP.py
index 9b74549d..a66cfc50 100644
--- a/lib/dns/rdtypes/ANY/RP.py
+++ b/lib/dns/rdtypes/ANY/RP.py
@@ -37,7 +37,7 @@ class RP(dns.rdata.Rdata):
def to_text(self, origin=None, relativize=True, **kw):
mbox = self.mbox.choose_relativity(origin, relativize)
txt = self.txt.choose_relativity(origin, relativize)
- return "{} {}".format(str(mbox), str(txt))
+ return f"{str(mbox)} {str(txt)}"
@classmethod
def from_text(
diff --git a/lib/dns/rdtypes/ANY/TKEY.py b/lib/dns/rdtypes/ANY/TKEY.py
index 5b490b82..75f62249 100644
--- a/lib/dns/rdtypes/ANY/TKEY.py
+++ b/lib/dns/rdtypes/ANY/TKEY.py
@@ -69,7 +69,7 @@ class TKEY(dns.rdata.Rdata):
dns.rdata._base64ify(self.key, 0),
)
if len(self.other) > 0:
- text += " %s" % (dns.rdata._base64ify(self.other, 0))
+ text += f" {dns.rdata._base64ify(self.other, 0)}"
return text
diff --git a/lib/dns/rdtypes/ANY/WALLET.py b/lib/dns/rdtypes/ANY/WALLET.py
new file mode 100644
index 00000000..ff464763
--- /dev/null
+++ b/lib/dns/rdtypes/ANY/WALLET.py
@@ -0,0 +1,9 @@
+# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
+
+import dns.immutable
+import dns.rdtypes.txtbase
+
+
+@dns.immutable.immutable
+class WALLET(dns.rdtypes.txtbase.TXTBase):
+ """WALLET record"""
diff --git a/lib/dns/rdtypes/ANY/X25.py b/lib/dns/rdtypes/ANY/X25.py
index 8375611d..2436ddb6 100644
--- a/lib/dns/rdtypes/ANY/X25.py
+++ b/lib/dns/rdtypes/ANY/X25.py
@@ -36,7 +36,7 @@ class X25(dns.rdata.Rdata):
self.address = self._as_bytes(address, True, 255)
def to_text(self, origin=None, relativize=True, **kw):
- return '"%s"' % dns.rdata._escapify(self.address)
+ return f'"{dns.rdata._escapify(self.address)}"'
@classmethod
def from_text(
diff --git a/lib/dns/rdtypes/ANY/__init__.py b/lib/dns/rdtypes/ANY/__init__.py
index 3824a0a0..647b215b 100644
--- a/lib/dns/rdtypes/ANY/__init__.py
+++ b/lib/dns/rdtypes/ANY/__init__.py
@@ -51,6 +51,7 @@ __all__ = [
"OPENPGPKEY",
"OPT",
"PTR",
+ "RESINFO",
"RP",
"RRSIG",
"RT",
@@ -63,6 +64,7 @@ __all__ = [
"TSIG",
"TXT",
"URI",
+ "WALLET",
"X25",
"ZONEMD",
]
diff --git a/lib/dns/rdtypes/CH/A.py b/lib/dns/rdtypes/CH/A.py
index 583a88ac..832e8d3a 100644
--- a/lib/dns/rdtypes/CH/A.py
+++ b/lib/dns/rdtypes/CH/A.py
@@ -37,7 +37,7 @@ class A(dns.rdata.Rdata):
def to_text(self, origin=None, relativize=True, **kw):
domain = self.domain.choose_relativity(origin, relativize)
- return "%s %o" % (domain, self.address)
+ return f"{domain} {self.address:o}"
@classmethod
def from_text(
diff --git a/lib/dns/rdtypes/IN/NSAP.py b/lib/dns/rdtypes/IN/NSAP.py
index a4854b3f..d55edb73 100644
--- a/lib/dns/rdtypes/IN/NSAP.py
+++ b/lib/dns/rdtypes/IN/NSAP.py
@@ -36,7 +36,7 @@ class NSAP(dns.rdata.Rdata):
self.address = self._as_bytes(address)
def to_text(self, origin=None, relativize=True, **kw):
- return "0x%s" % binascii.hexlify(self.address).decode()
+ return f"0x{binascii.hexlify(self.address).decode()}"
@classmethod
def from_text(
diff --git a/lib/dns/rdtypes/euibase.py b/lib/dns/rdtypes/euibase.py
index 751087b4..a39c166b 100644
--- a/lib/dns/rdtypes/euibase.py
+++ b/lib/dns/rdtypes/euibase.py
@@ -36,7 +36,7 @@ class EUIBase(dns.rdata.Rdata):
self.eui = self._as_bytes(eui)
if len(self.eui) != self.byte_len:
raise dns.exception.FormError(
- "EUI%s rdata has to have %s bytes" % (self.byte_len * 8, self.byte_len)
+ f"EUI{self.byte_len * 8} rdata has to have {self.byte_len} bytes"
)
def to_text(self, origin=None, relativize=True, **kw):
@@ -49,16 +49,16 @@ class EUIBase(dns.rdata.Rdata):
text = tok.get_string()
if len(text) != cls.text_len:
raise dns.exception.SyntaxError(
- "Input text must have %s characters" % cls.text_len
+ f"Input text must have {cls.text_len} characters"
)
for i in range(2, cls.byte_len * 3 - 1, 3):
if text[i] != "-":
- raise dns.exception.SyntaxError("Dash expected at position %s" % i)
+ raise dns.exception.SyntaxError(f"Dash expected at position {i}")
text = text.replace("-", "")
try:
data = binascii.unhexlify(text.encode())
except (ValueError, TypeError) as ex:
- raise dns.exception.SyntaxError("Hex decoding error: %s" % str(ex))
+ raise dns.exception.SyntaxError(f"Hex decoding error: {str(ex)}")
return cls(rdclass, rdtype, data)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
diff --git a/lib/dns/rdtypes/svcbbase.py b/lib/dns/rdtypes/svcbbase.py
index 05652413..a2b15b92 100644
--- a/lib/dns/rdtypes/svcbbase.py
+++ b/lib/dns/rdtypes/svcbbase.py
@@ -35,6 +35,7 @@ class ParamKey(dns.enum.IntEnum):
ECH = 5
IPV6HINT = 6
DOHPATH = 7
+ OHTTP = 8
@classmethod
def _maximum(cls):
@@ -396,6 +397,36 @@ class ECHParam(Param):
file.write(self.ech)
+@dns.immutable.immutable
+class OHTTPParam(Param):
+ # We don't ever expect to instantiate this class, but we need
+ # a from_value() and a from_wire_parser(), so we just return None
+ # from the class methods when things are OK.
+
+ @classmethod
+ def emptiness(cls):
+ return Emptiness.ALWAYS
+
+ @classmethod
+ def from_value(cls, value):
+ if value is None or value == "":
+ return None
+ else:
+ raise ValueError("ohttp with non-empty value")
+
+ def to_text(self):
+ raise NotImplementedError # pragma: no cover
+
+ @classmethod
+ def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613
+ if parser.remaining() != 0:
+ raise dns.exception.FormError
+ return None
+
+ def to_wire(self, file, origin=None): # pylint: disable=W0613
+ raise NotImplementedError # pragma: no cover
+
+
_class_for_key = {
ParamKey.MANDATORY: MandatoryParam,
ParamKey.ALPN: ALPNParam,
@@ -404,6 +435,7 @@ _class_for_key = {
ParamKey.IPV4HINT: IPv4HintParam,
ParamKey.ECH: ECHParam,
ParamKey.IPV6HINT: IPv6HintParam,
+ ParamKey.OHTTP: OHTTPParam,
}
diff --git a/lib/dns/rdtypes/txtbase.py b/lib/dns/rdtypes/txtbase.py
index 44d6df57..73db6d9e 100644
--- a/lib/dns/rdtypes/txtbase.py
+++ b/lib/dns/rdtypes/txtbase.py
@@ -50,6 +50,8 @@ class TXTBase(dns.rdata.Rdata):
self.strings: Tuple[bytes] = self._as_tuple(
strings, lambda x: self._as_bytes(x, True, 255)
)
+ if len(self.strings) == 0:
+ raise ValueError("the list of strings must not be empty")
def to_text(
self,
@@ -60,7 +62,7 @@ class TXTBase(dns.rdata.Rdata):
txt = ""
prefix = ""
for s in self.strings:
- txt += '{}"{}"'.format(prefix, dns.rdata._escapify(s))
+ txt += f'{prefix}"{dns.rdata._escapify(s)}"'
prefix = " "
return txt
diff --git a/lib/dns/rdtypes/util.py b/lib/dns/rdtypes/util.py
index 54908fdc..653a0bf2 100644
--- a/lib/dns/rdtypes/util.py
+++ b/lib/dns/rdtypes/util.py
@@ -231,7 +231,7 @@ def weighted_processing_order(iterable):
total = sum(rdata._processing_weight() or _no_weight for rdata in rdatas)
while len(rdatas) > 1:
r = random.uniform(0, total)
- for n, rdata in enumerate(rdatas):
+ for n, rdata in enumerate(rdatas): # noqa: B007
weight = rdata._processing_weight() or _no_weight
if weight > r:
break
diff --git a/lib/dns/resolver.py b/lib/dns/resolver.py
index f08f824d..3ba76e31 100644
--- a/lib/dns/resolver.py
+++ b/lib/dns/resolver.py
@@ -36,6 +36,7 @@ import dns.ipv4
import dns.ipv6
import dns.message
import dns.name
+import dns.rdata
import dns.nameserver
import dns.query
import dns.rcode
@@ -45,7 +46,7 @@ import dns.rdtypes.svcbbase
import dns.reversename
import dns.tsig
-if sys.platform == "win32":
+if sys.platform == "win32": # pragma: no cover
import dns.win32util
@@ -83,7 +84,7 @@ class NXDOMAIN(dns.exception.DNSException):
else:
msg = "The DNS query name does not exist"
qnames = ", ".join(map(str, qnames))
- return "{}: {}".format(msg, qnames)
+ return f"{msg}: {qnames}"
@property
def canonical_name(self):
@@ -96,7 +97,7 @@ class NXDOMAIN(dns.exception.DNSException):
cname = response.canonical_name()
if cname != qname:
return cname
- except Exception:
+ except Exception: # pragma: no cover
# We can just eat this exception as it means there was
# something wrong with the response.
pass
@@ -154,7 +155,7 @@ def _errors_to_text(errors: List[ErrorTuple]) -> List[str]:
"""Turn a resolution errors trace into a list of text."""
texts = []
for err in errors:
- texts.append("Server {} answered {}".format(err[0], err[3]))
+ texts.append(f"Server {err[0]} answered {err[3]}")
return texts
@@ -162,7 +163,7 @@ class LifetimeTimeout(dns.exception.Timeout):
"""The resolution lifetime expired."""
msg = "The resolution lifetime expired."
- fmt = "%s after {timeout:.3f} seconds: {errors}" % msg[:-1]
+ fmt = f"{msg[:-1]} after {{timeout:.3f}} seconds: {{errors}}"
supp_kwargs = {"timeout", "errors"}
# We do this as otherwise mypy complains about unexpected keyword argument
@@ -211,7 +212,7 @@ class NoNameservers(dns.exception.DNSException):
"""
msg = "All nameservers failed to answer the query."
- fmt = "%s {query}: {errors}" % msg[:-1]
+ fmt = f"{msg[:-1]} {{query}}: {{errors}}"
supp_kwargs = {"request", "errors"}
# We do this as otherwise mypy complains about unexpected keyword argument
@@ -297,7 +298,7 @@ class Answer:
def __len__(self) -> int:
return self.rrset and len(self.rrset) or 0
- def __iter__(self):
+ def __iter__(self) -> Iterator[dns.rdata.Rdata]:
return self.rrset and iter(self.rrset) or iter(tuple())
def __getitem__(self, i):
@@ -334,7 +335,7 @@ class HostAnswers(Answers):
answers[dns.rdatatype.A] = v4
return answers
- # Returns pairs of (address, family) from this result, potentiallys
+ # Returns pairs of (address, family) from this result, potentially
# filtering by address family.
def addresses_and_families(
self, family: int = socket.AF_UNSPEC
@@ -347,7 +348,7 @@ class HostAnswers(Answers):
answer = self.get(dns.rdatatype.AAAA)
elif family == socket.AF_INET:
answer = self.get(dns.rdatatype.A)
- else:
+ else: # pragma: no cover
raise NotImplementedError(f"unknown address family {family}")
if answer:
for rdata in answer:
@@ -938,7 +939,7 @@ class BaseResolver:
self.reset()
if configure:
- if sys.platform == "win32":
+ if sys.platform == "win32": # pragma: no cover
self.read_registry()
elif filename:
self.read_resolv_conf(filename)
@@ -947,7 +948,7 @@ class BaseResolver:
"""Reset all resolver configuration to the defaults."""
self.domain = dns.name.Name(dns.name.from_text(socket.gethostname())[1:])
- if len(self.domain) == 0:
+ if len(self.domain) == 0: # pragma: no cover
self.domain = dns.name.root
self._nameservers = []
self.nameserver_ports = {}
@@ -1040,7 +1041,7 @@ class BaseResolver:
# setter logic, with additonal checking and enrichment.
self.nameservers = nameservers
- def read_registry(self) -> None:
+ def read_registry(self) -> None: # pragma: no cover
"""Extract resolver configuration from the Windows registry."""
try:
info = dns.win32util.get_dns_info() # type: ignore
@@ -1205,9 +1206,7 @@ class BaseResolver:
enriched_nameservers.append(enriched_nameserver)
else:
raise ValueError(
- "nameservers must be a list or tuple (not a {})".format(
- type(nameservers)
- )
+ f"nameservers must be a list or tuple (not a {type(nameservers)})"
)
return enriched_nameservers
@@ -1431,7 +1430,7 @@ class Resolver(BaseResolver):
elif family == socket.AF_INET6:
v6 = self.resolve(name, dns.rdatatype.AAAA, **modified_kwargs)
return HostAnswers.make(v6=v6)
- elif family != socket.AF_UNSPEC:
+ elif family != socket.AF_UNSPEC: # pragma: no cover
raise NotImplementedError(f"unknown address family {family}")
raise_on_no_answer = modified_kwargs.pop("raise_on_no_answer", True)
@@ -1515,7 +1514,7 @@ class Resolver(BaseResolver):
nameservers = dns._ddr._get_nameservers_sync(answer, timeout)
if len(nameservers) > 0:
self.nameservers = nameservers
- except Exception:
+ except Exception: # pragma: no cover
pass
@@ -1640,7 +1639,7 @@ def canonical_name(name: Union[dns.name.Name, str]) -> dns.name.Name:
return get_default_resolver().canonical_name(name)
-def try_ddr(lifetime: float = 5.0) -> None:
+def try_ddr(lifetime: float = 5.0) -> None: # pragma: no cover
"""Try to update the default resolver's nameservers using Discovery of Designated
Resolvers (DDR). If successful, the resolver will subsequently use
DNS-over-HTTPS or DNS-over-TLS for future queries.
@@ -1926,7 +1925,7 @@ def _getnameinfo(sockaddr, flags=0):
family = socket.AF_INET
tuples = _getaddrinfo(host, port, family, socket.SOCK_STREAM, socket.SOL_TCP, 0)
if len(tuples) > 1:
- raise socket.error("sockaddr resolved to multiple addresses")
+ raise OSError("sockaddr resolved to multiple addresses")
addr = tuples[0][4][0]
if flags & socket.NI_DGRAM:
pname = "udp"
@@ -1961,7 +1960,7 @@ def _getfqdn(name=None):
(name, _, _) = _gethostbyaddr(name)
# Python's version checks aliases too, but our gethostbyname
# ignores them, so we do so here as well.
- except Exception:
+ except Exception: # pragma: no cover
pass
return name
diff --git a/lib/dns/set.py b/lib/dns/set.py
index f0fb0d50..ae8f0dd5 100644
--- a/lib/dns/set.py
+++ b/lib/dns/set.py
@@ -21,10 +21,11 @@ import itertools
class Set:
"""A simple set class.
- This class was originally used to deal with sets being missing in
- ancient versions of python, but dnspython will continue to use it
- as these sets are based on lists and are thus indexable, and this
- ability is widely used in dnspython applications.
+ This class was originally used to deal with python not having a set class, and
+ originally the class used lists in its implementation. The ordered and indexable
+ nature of RRsets and Rdatasets is unfortunately widely used in dnspython
+ applications, so for backwards compatibility sets continue to be a custom class, now
+ based on an ordered dictionary.
"""
__slots__ = ["items"]
@@ -43,7 +44,7 @@ class Set:
self.add(item) # lgtm[py/init-calls-subclass]
def __repr__(self):
- return "dns.set.Set(%s)" % repr(list(self.items.keys()))
+ return f"dns.set.Set({repr(list(self.items.keys()))})" # pragma: no cover
def add(self, item):
"""Add an item to the set."""
diff --git a/lib/dns/tokenizer.py b/lib/dns/tokenizer.py
index 454cac4a..ab205bc3 100644
--- a/lib/dns/tokenizer.py
+++ b/lib/dns/tokenizer.py
@@ -528,7 +528,7 @@ class Tokenizer:
if value < 0 or value > 65535:
if base == 8:
raise dns.exception.SyntaxError(
- "%o is not an octal unsigned 16-bit integer" % value
+ f"{value:o} is not an octal unsigned 16-bit integer"
)
else:
raise dns.exception.SyntaxError(
diff --git a/lib/dns/transaction.py b/lib/dns/transaction.py
index 84e54f7d..aa2e1160 100644
--- a/lib/dns/transaction.py
+++ b/lib/dns/transaction.py
@@ -486,7 +486,7 @@ class Transaction:
if exact:
raise DeleteNotExact(f"{method}: missing rdataset")
else:
- self._delete_rdataset(name, rdtype, covers)
+ self._checked_delete_rdataset(name, rdtype, covers)
return
else:
rdataset = self._rdataset_from_args(method, True, args)
@@ -529,8 +529,6 @@ class Transaction:
def _end(self, commit):
self._check_ended()
- if self._ended:
- raise AlreadyEnded
try:
self._end_transaction(commit)
finally:
diff --git a/lib/dns/ttl.py b/lib/dns/ttl.py
index 264b0338..b9a99fe3 100644
--- a/lib/dns/ttl.py
+++ b/lib/dns/ttl.py
@@ -73,7 +73,7 @@ def from_text(text: str) -> int:
elif c == "s":
total += current
else:
- raise BadTTL("unknown unit '%s'" % c)
+ raise BadTTL(f"unknown unit '{c}'")
current = 0
need_digit = True
if not current == 0:
diff --git a/lib/dns/version.py b/lib/dns/version.py
index 251f2583..9ed2ce19 100644
--- a/lib/dns/version.py
+++ b/lib/dns/version.py
@@ -20,9 +20,9 @@
#: MAJOR
MAJOR = 2
#: MINOR
-MINOR = 6
+MINOR = 7
#: MICRO
-MICRO = 1
+MICRO = 0
#: RELEASELEVEL
RELEASELEVEL = 0x0F
#: SERIAL
diff --git a/lib/dns/win32util.py b/lib/dns/win32util.py
index aaa7e93e..9ed3f11b 100644
--- a/lib/dns/win32util.py
+++ b/lib/dns/win32util.py
@@ -13,8 +13,8 @@ if sys.platform == "win32":
# Keep pylint quiet on non-windows.
try:
- WindowsError is None # pylint: disable=used-before-assignment
- except KeyError:
+ _ = WindowsError # pylint: disable=used-before-assignment
+ except NameError:
WindowsError = Exception
if dns._features.have("wmi"):
@@ -44,6 +44,7 @@ if sys.platform == "win32":
if _have_wmi:
class _WMIGetter(threading.Thread):
+ # pylint: disable=possibly-used-before-assignment
def __init__(self):
super().__init__()
self.info = DnsInfo()
@@ -82,32 +83,21 @@ if sys.platform == "win32":
def __init__(self):
self.info = DnsInfo()
- def _determine_split_char(self, entry):
- #
- # The windows registry irritatingly changes the list element
- # delimiter in between ' ' and ',' (and vice-versa) in various
- # versions of windows.
- #
- if entry.find(" ") >= 0:
- split_char = " "
- elif entry.find(",") >= 0:
- split_char = ","
- else:
- # probably a singleton; treat as a space-separated list.
- split_char = " "
- return split_char
+ def _split(self, text):
+ # The windows registry has used both " " and "," as a delimiter, and while
+ # it is currently using "," in Windows 10 and later, updates can seemingly
+ # leave a space in too, e.g. "a, b". So we just convert all commas to
+ # spaces, and use split() in its default configuration, which splits on
+ # all whitespace and ignores empty strings.
+ return text.replace(",", " ").split()
def _config_nameservers(self, nameservers):
- split_char = self._determine_split_char(nameservers)
- ns_list = nameservers.split(split_char)
- for ns in ns_list:
+ for ns in self._split(nameservers):
if ns not in self.info.nameservers:
self.info.nameservers.append(ns)
def _config_search(self, search):
- split_char = self._determine_split_char(search)
- search_list = search.split(split_char)
- for s in search_list:
+ for s in self._split(search):
s = _config_domain(s)
if s not in self.info.search:
self.info.search.append(s)
@@ -164,7 +154,7 @@ if sys.platform == "win32":
lm,
r"SYSTEM\CurrentControlSet\Control\Network"
r"\{4D36E972-E325-11CE-BFC1-08002BE10318}"
- r"\%s\Connection" % guid,
+ rf"\{guid}\Connection",
)
try:
@@ -177,7 +167,7 @@ if sys.platform == "win32":
raise ValueError # pragma: no cover
device_key = winreg.OpenKey(
- lm, r"SYSTEM\CurrentControlSet\Enum\%s" % pnp_id
+ lm, rf"SYSTEM\CurrentControlSet\Enum\{pnp_id}"
)
try:
@@ -232,7 +222,7 @@ if sys.platform == "win32":
self._config_fromkey(key, False)
finally:
key.Close()
- except EnvironmentError:
+ except OSError:
break
finally:
interfaces.Close()
diff --git a/lib/dns/xfr.py b/lib/dns/xfr.py
index dd247d33..520aa32d 100644
--- a/lib/dns/xfr.py
+++ b/lib/dns/xfr.py
@@ -33,7 +33,7 @@ class TransferError(dns.exception.DNSException):
"""A zone transfer response got a non-zero rcode."""
def __init__(self, rcode):
- message = "Zone transfer error: %s" % dns.rcode.to_text(rcode)
+ message = f"Zone transfer error: {dns.rcode.to_text(rcode)}"
super().__init__(message)
self.rcode = rcode
diff --git a/lib/dns/zonefile.py b/lib/dns/zonefile.py
index af064e73..d74510b2 100644
--- a/lib/dns/zonefile.py
+++ b/lib/dns/zonefile.py
@@ -230,7 +230,7 @@ class Reader:
try:
rdtype = dns.rdatatype.from_text(token.value)
except Exception:
- raise dns.exception.SyntaxError("unknown rdatatype '%s'" % token.value)
+ raise dns.exception.SyntaxError(f"unknown rdatatype '{token.value}'")
try:
rd = dns.rdata.from_text(
@@ -251,9 +251,7 @@ class Reader:
# We convert them to syntax errors so that we can emit
# helpful filename:line info.
(ty, va) = sys.exc_info()[:2]
- raise dns.exception.SyntaxError(
- "caught exception {}: {}".format(str(ty), str(va))
- )
+ raise dns.exception.SyntaxError(f"caught exception {str(ty)}: {str(va)}")
if not self.default_ttl_known and rdtype == dns.rdatatype.SOA:
# The pre-RFC2308 and pre-BIND9 behavior inherits the zone default
@@ -281,41 +279,41 @@ class Reader:
# Sometimes there are modifiers in the hostname. These come after
# the dollar sign. They are in the form: ${offset[,width[,base]]}.
# Make names
+ mod = ""
+ sign = "+"
+ offset = "0"
+ width = "0"
+ base = "d"
g1 = is_generate1.match(side)
if g1:
mod, sign, offset, width, base = g1.groups()
if sign == "":
sign = "+"
- g2 = is_generate2.match(side)
- if g2:
- mod, sign, offset = g2.groups()
- if sign == "":
- sign = "+"
- width = 0
- base = "d"
- g3 = is_generate3.match(side)
- if g3:
- mod, sign, offset, width = g3.groups()
- if sign == "":
- sign = "+"
- base = "d"
+ else:
+ g2 = is_generate2.match(side)
+ if g2:
+ mod, sign, offset = g2.groups()
+ if sign == "":
+ sign = "+"
+ width = "0"
+ base = "d"
+ else:
+ g3 = is_generate3.match(side)
+ if g3:
+ mod, sign, offset, width = g3.groups()
+ if sign == "":
+ sign = "+"
+ base = "d"
- if not (g1 or g2 or g3):
- mod = ""
- sign = "+"
- offset = 0
- width = 0
- base = "d"
-
- offset = int(offset)
- width = int(width)
+ ioffset = int(offset)
+ iwidth = int(width)
if sign not in ["+", "-"]:
- raise dns.exception.SyntaxError("invalid offset sign %s" % sign)
+ raise dns.exception.SyntaxError(f"invalid offset sign {sign}")
if base not in ["d", "o", "x", "X", "n", "N"]:
- raise dns.exception.SyntaxError("invalid type %s" % base)
+ raise dns.exception.SyntaxError(f"invalid type {base}")
- return mod, sign, offset, width, base
+ return mod, sign, ioffset, iwidth, base
def _generate_line(self):
# range lhs [ttl] [class] type rhs [ comment ]
@@ -377,7 +375,7 @@ class Reader:
if not token.is_identifier():
raise dns.exception.SyntaxError
except Exception:
- raise dns.exception.SyntaxError("unknown rdatatype '%s'" % token.value)
+ raise dns.exception.SyntaxError(f"unknown rdatatype '{token.value}'")
# rhs (required)
rhs = token.value
@@ -412,8 +410,8 @@ class Reader:
lzfindex = _format_index(lindex, lbase, lwidth)
rzfindex = _format_index(rindex, rbase, rwidth)
- name = lhs.replace("$%s" % (lmod), lzfindex)
- rdata = rhs.replace("$%s" % (rmod), rzfindex)
+ name = lhs.replace(f"${lmod}", lzfindex)
+ rdata = rhs.replace(f"${rmod}", rzfindex)
self.last_name = dns.name.from_text(
name, self.current_origin, self.tok.idna_codec
@@ -445,7 +443,7 @@ class Reader:
# helpful filename:line info.
(ty, va) = sys.exc_info()[:2]
raise dns.exception.SyntaxError(
- "caught exception %s: %s" % (str(ty), str(va))
+ f"caught exception {str(ty)}: {str(va)}"
)
self.txn.add(name, ttl, rd)
@@ -528,7 +526,7 @@ class Reader:
self.default_ttl_known,
)
)
- self.current_file = open(filename, "r")
+ self.current_file = open(filename)
self.tok = dns.tokenizer.Tokenizer(self.current_file, filename)
self.current_origin = new_origin
elif c == "$GENERATE":
diff --git a/lib/idna/__init__.py b/lib/idna/__init__.py
index a40eeafc..cfdc030a 100644
--- a/lib/idna/__init__.py
+++ b/lib/idna/__init__.py
@@ -1,4 +1,3 @@
-from .package_data import __version__
from .core import (
IDNABidiError,
IDNAError,
@@ -20,8 +19,10 @@ from .core import (
valid_string_length,
)
from .intranges import intranges_contain
+from .package_data import __version__
__all__ = [
+ "__version__",
"IDNABidiError",
"IDNAError",
"InvalidCodepoint",
diff --git a/lib/idna/codec.py b/lib/idna/codec.py
index c855a4de..913abfd6 100644
--- a/lib/idna/codec.py
+++ b/lib/idna/codec.py
@@ -1,49 +1,51 @@
-from .core import encode, decode, alabel, ulabel, IDNAError
import codecs
import re
-from typing import Any, Tuple, Optional
+from typing import Any, Optional, Tuple
+
+from .core import IDNAError, alabel, decode, encode, ulabel
+
+_unicode_dots_re = re.compile("[\u002e\u3002\uff0e\uff61]")
-_unicode_dots_re = re.compile('[\u002e\u3002\uff0e\uff61]')
class Codec(codecs.Codec):
-
- def encode(self, data: str, errors: str = 'strict') -> Tuple[bytes, int]:
- if errors != 'strict':
- raise IDNAError('Unsupported error handling \"{}\"'.format(errors))
+ def encode(self, data: str, errors: str = "strict") -> Tuple[bytes, int]:
+ if errors != "strict":
+ raise IDNAError('Unsupported error handling "{}"'.format(errors))
if not data:
return b"", 0
return encode(data), len(data)
- def decode(self, data: bytes, errors: str = 'strict') -> Tuple[str, int]:
- if errors != 'strict':
- raise IDNAError('Unsupported error handling \"{}\"'.format(errors))
+ def decode(self, data: bytes, errors: str = "strict") -> Tuple[str, int]:
+ if errors != "strict":
+ raise IDNAError('Unsupported error handling "{}"'.format(errors))
if not data:
- return '', 0
+ return "", 0
return decode(data), len(data)
+
class IncrementalEncoder(codecs.BufferedIncrementalEncoder):
def _buffer_encode(self, data: str, errors: str, final: bool) -> Tuple[bytes, int]:
- if errors != 'strict':
- raise IDNAError('Unsupported error handling \"{}\"'.format(errors))
+ if errors != "strict":
+ raise IDNAError('Unsupported error handling "{}"'.format(errors))
if not data:
- return b'', 0
+ return b"", 0
labels = _unicode_dots_re.split(data)
- trailing_dot = b''
+ trailing_dot = b""
if labels:
if not labels[-1]:
- trailing_dot = b'.'
+ trailing_dot = b"."
del labels[-1]
elif not final:
# Keep potentially unfinished label until the next call
del labels[-1]
if labels:
- trailing_dot = b'.'
+ trailing_dot = b"."
result = []
size = 0
@@ -54,32 +56,33 @@ class IncrementalEncoder(codecs.BufferedIncrementalEncoder):
size += len(label)
# Join with U+002E
- result_bytes = b'.'.join(result) + trailing_dot
+ result_bytes = b".".join(result) + trailing_dot
size += len(trailing_dot)
return result_bytes, size
+
class IncrementalDecoder(codecs.BufferedIncrementalDecoder):
def _buffer_decode(self, data: Any, errors: str, final: bool) -> Tuple[str, int]:
- if errors != 'strict':
- raise IDNAError('Unsupported error handling \"{}\"'.format(errors))
+ if errors != "strict":
+ raise IDNAError('Unsupported error handling "{}"'.format(errors))
if not data:
- return ('', 0)
+ return ("", 0)
if not isinstance(data, str):
- data = str(data, 'ascii')
+ data = str(data, "ascii")
labels = _unicode_dots_re.split(data)
- trailing_dot = ''
+ trailing_dot = ""
if labels:
if not labels[-1]:
- trailing_dot = '.'
+ trailing_dot = "."
del labels[-1]
elif not final:
# Keep potentially unfinished label until the next call
del labels[-1]
if labels:
- trailing_dot = '.'
+ trailing_dot = "."
result = []
size = 0
@@ -89,7 +92,7 @@ class IncrementalDecoder(codecs.BufferedIncrementalDecoder):
size += 1
size += len(label)
- result_str = '.'.join(result) + trailing_dot
+ result_str = ".".join(result) + trailing_dot
size += len(trailing_dot)
return (result_str, size)
@@ -103,7 +106,7 @@ class StreamReader(Codec, codecs.StreamReader):
def search_function(name: str) -> Optional[codecs.CodecInfo]:
- if name != 'idna2008':
+ if name != "idna2008":
return None
return codecs.CodecInfo(
name=name,
@@ -115,4 +118,5 @@ def search_function(name: str) -> Optional[codecs.CodecInfo]:
streamreader=StreamReader,
)
+
codecs.register(search_function)
diff --git a/lib/idna/compat.py b/lib/idna/compat.py
index 786e6bda..1df9f2a7 100644
--- a/lib/idna/compat.py
+++ b/lib/idna/compat.py
@@ -1,13 +1,15 @@
-from .core import *
-from .codec import *
from typing import Any, Union
+from .core import decode, encode
+
+
def ToASCII(label: str) -> bytes:
return encode(label)
+
def ToUnicode(label: Union[bytes, bytearray]) -> str:
return decode(label)
-def nameprep(s: Any) -> None:
- raise NotImplementedError('IDNA 2008 does not utilise nameprep protocol')
+def nameprep(s: Any) -> None:
+ raise NotImplementedError("IDNA 2008 does not utilise nameprep protocol")
diff --git a/lib/idna/core.py b/lib/idna/core.py
index 0dae61ac..9115f123 100644
--- a/lib/idna/core.py
+++ b/lib/idna/core.py
@@ -1,31 +1,37 @@
-from . import idnadata
import bisect
-import unicodedata
import re
-from typing import Union, Optional
+import unicodedata
+from typing import Optional, Union
+
+from . import idnadata
from .intranges import intranges_contain
_virama_combining_class = 9
-_alabel_prefix = b'xn--'
-_unicode_dots_re = re.compile('[\u002e\u3002\uff0e\uff61]')
+_alabel_prefix = b"xn--"
+_unicode_dots_re = re.compile("[\u002e\u3002\uff0e\uff61]")
+
class IDNAError(UnicodeError):
- """ Base exception for all IDNA-encoding related problems """
+ """Base exception for all IDNA-encoding related problems"""
+
pass
class IDNABidiError(IDNAError):
- """ Exception when bidirectional requirements are not satisfied """
+ """Exception when bidirectional requirements are not satisfied"""
+
pass
class InvalidCodepoint(IDNAError):
- """ Exception when a disallowed or unallocated codepoint is used """
+ """Exception when a disallowed or unallocated codepoint is used"""
+
pass
class InvalidCodepointContext(IDNAError):
- """ Exception when the codepoint is not valid in the context it is used """
+ """Exception when the codepoint is not valid in the context it is used"""
+
pass
@@ -33,17 +39,20 @@ def _combining_class(cp: int) -> int:
v = unicodedata.combining(chr(cp))
if v == 0:
if not unicodedata.name(chr(cp)):
- raise ValueError('Unknown character in unicodedata')
+ raise ValueError("Unknown character in unicodedata")
return v
+
def _is_script(cp: str, script: str) -> bool:
return intranges_contain(ord(cp), idnadata.scripts[script])
+
def _punycode(s: str) -> bytes:
- return s.encode('punycode')
+ return s.encode("punycode")
+
def _unot(s: int) -> str:
- return 'U+{:04X}'.format(s)
+ return "U+{:04X}".format(s)
def valid_label_length(label: Union[bytes, str]) -> bool:
@@ -61,96 +70,106 @@ def valid_string_length(label: Union[bytes, str], trailing_dot: bool) -> bool:
def check_bidi(label: str, check_ltr: bool = False) -> bool:
# Bidi rules should only be applied if string contains RTL characters
bidi_label = False
- for (idx, cp) in enumerate(label, 1):
+ for idx, cp in enumerate(label, 1):
direction = unicodedata.bidirectional(cp)
- if direction == '':
+ if direction == "":
# String likely comes from a newer version of Unicode
- raise IDNABidiError('Unknown directionality in label {} at position {}'.format(repr(label), idx))
- if direction in ['R', 'AL', 'AN']:
+ raise IDNABidiError("Unknown directionality in label {} at position {}".format(repr(label), idx))
+ if direction in ["R", "AL", "AN"]:
bidi_label = True
if not bidi_label and not check_ltr:
return True
# Bidi rule 1
direction = unicodedata.bidirectional(label[0])
- if direction in ['R', 'AL']:
+ if direction in ["R", "AL"]:
rtl = True
- elif direction == 'L':
+ elif direction == "L":
rtl = False
else:
- raise IDNABidiError('First codepoint in label {} must be directionality L, R or AL'.format(repr(label)))
+ raise IDNABidiError("First codepoint in label {} must be directionality L, R or AL".format(repr(label)))
valid_ending = False
- number_type = None # type: Optional[str]
- for (idx, cp) in enumerate(label, 1):
+ number_type: Optional[str] = None
+ for idx, cp in enumerate(label, 1):
direction = unicodedata.bidirectional(cp)
if rtl:
# Bidi rule 2
- if not direction in ['R', 'AL', 'AN', 'EN', 'ES', 'CS', 'ET', 'ON', 'BN', 'NSM']:
- raise IDNABidiError('Invalid direction for codepoint at position {} in a right-to-left label'.format(idx))
+ if direction not in [
+ "R",
+ "AL",
+ "AN",
+ "EN",
+ "ES",
+ "CS",
+ "ET",
+ "ON",
+ "BN",
+ "NSM",
+ ]:
+ raise IDNABidiError("Invalid direction for codepoint at position {} in a right-to-left label".format(idx))
# Bidi rule 3
- if direction in ['R', 'AL', 'EN', 'AN']:
+ if direction in ["R", "AL", "EN", "AN"]:
valid_ending = True
- elif direction != 'NSM':
+ elif direction != "NSM":
valid_ending = False
# Bidi rule 4
- if direction in ['AN', 'EN']:
+ if direction in ["AN", "EN"]:
if not number_type:
number_type = direction
else:
if number_type != direction:
- raise IDNABidiError('Can not mix numeral types in a right-to-left label')
+ raise IDNABidiError("Can not mix numeral types in a right-to-left label")
else:
# Bidi rule 5
- if not direction in ['L', 'EN', 'ES', 'CS', 'ET', 'ON', 'BN', 'NSM']:
- raise IDNABidiError('Invalid direction for codepoint at position {} in a left-to-right label'.format(idx))
+ if direction not in ["L", "EN", "ES", "CS", "ET", "ON", "BN", "NSM"]:
+ raise IDNABidiError("Invalid direction for codepoint at position {} in a left-to-right label".format(idx))
# Bidi rule 6
- if direction in ['L', 'EN']:
+ if direction in ["L", "EN"]:
valid_ending = True
- elif direction != 'NSM':
+ elif direction != "NSM":
valid_ending = False
if not valid_ending:
- raise IDNABidiError('Label ends with illegal codepoint directionality')
+ raise IDNABidiError("Label ends with illegal codepoint directionality")
return True
def check_initial_combiner(label: str) -> bool:
- if unicodedata.category(label[0])[0] == 'M':
- raise IDNAError('Label begins with an illegal combining character')
+ if unicodedata.category(label[0])[0] == "M":
+ raise IDNAError("Label begins with an illegal combining character")
return True
def check_hyphen_ok(label: str) -> bool:
- if label[2:4] == '--':
- raise IDNAError('Label has disallowed hyphens in 3rd and 4th position')
- if label[0] == '-' or label[-1] == '-':
- raise IDNAError('Label must not start or end with a hyphen')
+ if label[2:4] == "--":
+ raise IDNAError("Label has disallowed hyphens in 3rd and 4th position")
+ if label[0] == "-" or label[-1] == "-":
+ raise IDNAError("Label must not start or end with a hyphen")
return True
def check_nfc(label: str) -> None:
- if unicodedata.normalize('NFC', label) != label:
- raise IDNAError('Label must be in Normalization Form C')
+ if unicodedata.normalize("NFC", label) != label:
+ raise IDNAError("Label must be in Normalization Form C")
def valid_contextj(label: str, pos: int) -> bool:
cp_value = ord(label[pos])
- if cp_value == 0x200c:
-
+ if cp_value == 0x200C:
if pos > 0:
if _combining_class(ord(label[pos - 1])) == _virama_combining_class:
return True
ok = False
- for i in range(pos-1, -1, -1):
+ for i in range(pos - 1, -1, -1):
joining_type = idnadata.joining_types.get(ord(label[i]))
- if joining_type == ord('T'):
+ if joining_type == ord("T"):
continue
- elif joining_type in [ord('L'), ord('D')]:
+ elif joining_type in [ord("L"), ord("D")]:
ok = True
break
else:
@@ -160,63 +179,61 @@ def valid_contextj(label: str, pos: int) -> bool:
return False
ok = False
- for i in range(pos+1, len(label)):
+ for i in range(pos + 1, len(label)):
joining_type = idnadata.joining_types.get(ord(label[i]))
- if joining_type == ord('T'):
+ if joining_type == ord("T"):
continue
- elif joining_type in [ord('R'), ord('D')]:
+ elif joining_type in [ord("R"), ord("D")]:
ok = True
break
else:
break
return ok
- if cp_value == 0x200d:
-
+ if cp_value == 0x200D:
if pos > 0:
if _combining_class(ord(label[pos - 1])) == _virama_combining_class:
return True
return False
else:
-
return False
def valid_contexto(label: str, pos: int, exception: bool = False) -> bool:
cp_value = ord(label[pos])
- if cp_value == 0x00b7:
- if 0 < pos < len(label)-1:
- if ord(label[pos - 1]) == 0x006c and ord(label[pos + 1]) == 0x006c:
+ if cp_value == 0x00B7:
+ if 0 < pos < len(label) - 1:
+ if ord(label[pos - 1]) == 0x006C and ord(label[pos + 1]) == 0x006C:
return True
return False
elif cp_value == 0x0375:
- if pos < len(label)-1 and len(label) > 1:
- return _is_script(label[pos + 1], 'Greek')
+ if pos < len(label) - 1 and len(label) > 1:
+ return _is_script(label[pos + 1], "Greek")
return False
- elif cp_value == 0x05f3 or cp_value == 0x05f4:
+ elif cp_value == 0x05F3 or cp_value == 0x05F4:
if pos > 0:
- return _is_script(label[pos - 1], 'Hebrew')
+ return _is_script(label[pos - 1], "Hebrew")
return False
- elif cp_value == 0x30fb:
+ elif cp_value == 0x30FB:
for cp in label:
- if cp == '\u30fb':
+ if cp == "\u30fb":
continue
- if _is_script(cp, 'Hiragana') or _is_script(cp, 'Katakana') or _is_script(cp, 'Han'):
+ if _is_script(cp, "Hiragana") or _is_script(cp, "Katakana") or _is_script(cp, "Han"):
return True
return False
elif 0x660 <= cp_value <= 0x669:
for cp in label:
- if 0x6f0 <= ord(cp) <= 0x06f9:
+ if 0x6F0 <= ord(cp) <= 0x06F9:
return False
return True
- elif 0x6f0 <= cp_value <= 0x6f9:
+ elif 0x6F0 <= cp_value <= 0x6F9:
for cp in label:
if 0x660 <= ord(cp) <= 0x0669:
return False
@@ -227,37 +244,49 @@ def valid_contexto(label: str, pos: int, exception: bool = False) -> bool:
def check_label(label: Union[str, bytes, bytearray]) -> None:
if isinstance(label, (bytes, bytearray)):
- label = label.decode('utf-8')
+ label = label.decode("utf-8")
if len(label) == 0:
- raise IDNAError('Empty Label')
+ raise IDNAError("Empty Label")
check_nfc(label)
check_hyphen_ok(label)
check_initial_combiner(label)
- for (pos, cp) in enumerate(label):
+ for pos, cp in enumerate(label):
cp_value = ord(cp)
- if intranges_contain(cp_value, idnadata.codepoint_classes['PVALID']):
+ if intranges_contain(cp_value, idnadata.codepoint_classes["PVALID"]):
continue
- elif intranges_contain(cp_value, idnadata.codepoint_classes['CONTEXTJ']):
- if not valid_contextj(label, pos):
- raise InvalidCodepointContext('Joiner {} not allowed at position {} in {}'.format(
- _unot(cp_value), pos+1, repr(label)))
- elif intranges_contain(cp_value, idnadata.codepoint_classes['CONTEXTO']):
+ elif intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTJ"]):
+ try:
+ if not valid_contextj(label, pos):
+ raise InvalidCodepointContext(
+ "Joiner {} not allowed at position {} in {}".format(_unot(cp_value), pos + 1, repr(label))
+ )
+ except ValueError:
+ raise IDNAError(
+ "Unknown codepoint adjacent to joiner {} at position {} in {}".format(
+ _unot(cp_value), pos + 1, repr(label)
+ )
+ )
+ elif intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTO"]):
if not valid_contexto(label, pos):
- raise InvalidCodepointContext('Codepoint {} not allowed at position {} in {}'.format(_unot(cp_value), pos+1, repr(label)))
+ raise InvalidCodepointContext(
+ "Codepoint {} not allowed at position {} in {}".format(_unot(cp_value), pos + 1, repr(label))
+ )
else:
- raise InvalidCodepoint('Codepoint {} at position {} of {} not allowed'.format(_unot(cp_value), pos+1, repr(label)))
+ raise InvalidCodepoint(
+ "Codepoint {} at position {} of {} not allowed".format(_unot(cp_value), pos + 1, repr(label))
+ )
check_bidi(label)
def alabel(label: str) -> bytes:
try:
- label_bytes = label.encode('ascii')
+ label_bytes = label.encode("ascii")
ulabel(label_bytes)
if not valid_label_length(label_bytes):
- raise IDNAError('Label too long')
+ raise IDNAError("Label too long")
return label_bytes
except UnicodeEncodeError:
pass
@@ -266,7 +295,7 @@ def alabel(label: str) -> bytes:
label_bytes = _alabel_prefix + _punycode(label)
if not valid_label_length(label_bytes):
- raise IDNAError('Label too long')
+ raise IDNAError("Label too long")
return label_bytes
@@ -274,7 +303,7 @@ def alabel(label: str) -> bytes:
def ulabel(label: Union[str, bytes, bytearray]) -> str:
if not isinstance(label, (bytes, bytearray)):
try:
- label_bytes = label.encode('ascii')
+ label_bytes = label.encode("ascii")
except UnicodeEncodeError:
check_label(label)
return label
@@ -283,19 +312,19 @@ def ulabel(label: Union[str, bytes, bytearray]) -> str:
label_bytes = label_bytes.lower()
if label_bytes.startswith(_alabel_prefix):
- label_bytes = label_bytes[len(_alabel_prefix):]
+ label_bytes = label_bytes[len(_alabel_prefix) :]
if not label_bytes:
- raise IDNAError('Malformed A-label, no Punycode eligible content found')
- if label_bytes.decode('ascii')[-1] == '-':
- raise IDNAError('A-label must not end with a hyphen')
+ raise IDNAError("Malformed A-label, no Punycode eligible content found")
+ if label_bytes.decode("ascii")[-1] == "-":
+ raise IDNAError("A-label must not end with a hyphen")
else:
check_label(label_bytes)
- return label_bytes.decode('ascii')
+ return label_bytes.decode("ascii")
try:
- label = label_bytes.decode('punycode')
+ label = label_bytes.decode("punycode")
except UnicodeError:
- raise IDNAError('Invalid A-label')
+ raise IDNAError("Invalid A-label")
check_label(label)
return label
@@ -303,52 +332,60 @@ def ulabel(label: Union[str, bytes, bytearray]) -> str:
def uts46_remap(domain: str, std3_rules: bool = True, transitional: bool = False) -> str:
"""Re-map the characters in the string according to UTS46 processing."""
from .uts46data import uts46data
- output = ''
+
+ output = ""
for pos, char in enumerate(domain):
code_point = ord(char)
try:
- uts46row = uts46data[code_point if code_point < 256 else
- bisect.bisect_left(uts46data, (code_point, 'Z')) - 1]
+ uts46row = uts46data[code_point if code_point < 256 else bisect.bisect_left(uts46data, (code_point, "Z")) - 1]
status = uts46row[1]
- replacement = None # type: Optional[str]
+ replacement: Optional[str] = None
if len(uts46row) == 3:
replacement = uts46row[2]
- if (status == 'V' or
- (status == 'D' and not transitional) or
- (status == '3' and not std3_rules and replacement is None)):
+ if (
+ status == "V"
+ or (status == "D" and not transitional)
+ or (status == "3" and not std3_rules and replacement is None)
+ ):
output += char
- elif replacement is not None and (status == 'M' or
- (status == '3' and not std3_rules) or
- (status == 'D' and transitional)):
+ elif replacement is not None and (
+ status == "M" or (status == "3" and not std3_rules) or (status == "D" and transitional)
+ ):
output += replacement
- elif status != 'I':
+ elif status != "I":
raise IndexError()
except IndexError:
raise InvalidCodepoint(
- 'Codepoint {} not allowed at position {} in {}'.format(
- _unot(code_point), pos + 1, repr(domain)))
+ "Codepoint {} not allowed at position {} in {}".format(_unot(code_point), pos + 1, repr(domain))
+ )
- return unicodedata.normalize('NFC', output)
+ return unicodedata.normalize("NFC", output)
-def encode(s: Union[str, bytes, bytearray], strict: bool = False, uts46: bool = False, std3_rules: bool = False, transitional: bool = False) -> bytes:
+def encode(
+ s: Union[str, bytes, bytearray],
+ strict: bool = False,
+ uts46: bool = False,
+ std3_rules: bool = False,
+ transitional: bool = False,
+) -> bytes:
if not isinstance(s, str):
try:
- s = str(s, 'ascii')
+ s = str(s, "ascii")
except UnicodeDecodeError:
- raise IDNAError('should pass a unicode string to the function rather than a byte string.')
+ raise IDNAError("should pass a unicode string to the function rather than a byte string.")
if uts46:
s = uts46_remap(s, std3_rules, transitional)
trailing_dot = False
result = []
if strict:
- labels = s.split('.')
+ labels = s.split(".")
else:
labels = _unicode_dots_re.split(s)
- if not labels or labels == ['']:
- raise IDNAError('Empty domain')
- if labels[-1] == '':
+ if not labels or labels == [""]:
+ raise IDNAError("Empty domain")
+ if labels[-1] == "":
del labels[-1]
trailing_dot = True
for label in labels:
@@ -356,21 +393,26 @@ def encode(s: Union[str, bytes, bytearray], strict: bool = False, uts46: bool =
if s:
result.append(s)
else:
- raise IDNAError('Empty label')
+ raise IDNAError("Empty label")
if trailing_dot:
- result.append(b'')
- s = b'.'.join(result)
+ result.append(b"")
+ s = b".".join(result)
if not valid_string_length(s, trailing_dot):
- raise IDNAError('Domain too long')
+ raise IDNAError("Domain too long")
return s
-def decode(s: Union[str, bytes, bytearray], strict: bool = False, uts46: bool = False, std3_rules: bool = False) -> str:
+def decode(
+ s: Union[str, bytes, bytearray],
+ strict: bool = False,
+ uts46: bool = False,
+ std3_rules: bool = False,
+) -> str:
try:
if not isinstance(s, str):
- s = str(s, 'ascii')
+ s = str(s, "ascii")
except UnicodeDecodeError:
- raise IDNAError('Invalid ASCII in A-label')
+ raise IDNAError("Invalid ASCII in A-label")
if uts46:
s = uts46_remap(s, std3_rules, False)
trailing_dot = False
@@ -378,9 +420,9 @@ def decode(s: Union[str, bytes, bytearray], strict: bool = False, uts46: bool =
if not strict:
labels = _unicode_dots_re.split(s)
else:
- labels = s.split('.')
- if not labels or labels == ['']:
- raise IDNAError('Empty domain')
+ labels = s.split(".")
+ if not labels or labels == [""]:
+ raise IDNAError("Empty domain")
if not labels[-1]:
del labels[-1]
trailing_dot = True
@@ -389,7 +431,7 @@ def decode(s: Union[str, bytes, bytearray], strict: bool = False, uts46: bool =
if s:
result.append(s)
else:
- raise IDNAError('Empty label')
+ raise IDNAError("Empty label")
if trailing_dot:
- result.append('')
- return '.'.join(result)
+ result.append("")
+ return ".".join(result)
diff --git a/lib/idna/idnadata.py b/lib/idna/idnadata.py
index c61dcf97..4be60046 100644
--- a/lib/idna/idnadata.py
+++ b/lib/idna/idnadata.py
@@ -1,107 +1,107 @@
# This file is automatically generated by tools/idna-data
-__version__ = '15.1.0'
+__version__ = "15.1.0"
scripts = {
- 'Greek': (
+ "Greek": (
0x37000000374,
0x37500000378,
- 0x37a0000037e,
- 0x37f00000380,
+ 0x37A0000037E,
+ 0x37F00000380,
0x38400000385,
0x38600000387,
- 0x3880000038b,
- 0x38c0000038d,
- 0x38e000003a2,
- 0x3a3000003e2,
- 0x3f000000400,
- 0x1d2600001d2b,
- 0x1d5d00001d62,
- 0x1d6600001d6b,
- 0x1dbf00001dc0,
- 0x1f0000001f16,
- 0x1f1800001f1e,
- 0x1f2000001f46,
- 0x1f4800001f4e,
- 0x1f5000001f58,
- 0x1f5900001f5a,
- 0x1f5b00001f5c,
- 0x1f5d00001f5e,
- 0x1f5f00001f7e,
- 0x1f8000001fb5,
- 0x1fb600001fc5,
- 0x1fc600001fd4,
- 0x1fd600001fdc,
- 0x1fdd00001ff0,
- 0x1ff200001ff5,
- 0x1ff600001fff,
+ 0x3880000038B,
+ 0x38C0000038D,
+ 0x38E000003A2,
+ 0x3A3000003E2,
+ 0x3F000000400,
+ 0x1D2600001D2B,
+ 0x1D5D00001D62,
+ 0x1D6600001D6B,
+ 0x1DBF00001DC0,
+ 0x1F0000001F16,
+ 0x1F1800001F1E,
+ 0x1F2000001F46,
+ 0x1F4800001F4E,
+ 0x1F5000001F58,
+ 0x1F5900001F5A,
+ 0x1F5B00001F5C,
+ 0x1F5D00001F5E,
+ 0x1F5F00001F7E,
+ 0x1F8000001FB5,
+ 0x1FB600001FC5,
+ 0x1FC600001FD4,
+ 0x1FD600001FDC,
+ 0x1FDD00001FF0,
+ 0x1FF200001FF5,
+ 0x1FF600001FFF,
0x212600002127,
- 0xab650000ab66,
- 0x101400001018f,
- 0x101a0000101a1,
- 0x1d2000001d246,
+ 0xAB650000AB66,
+ 0x101400001018F,
+ 0x101A0000101A1,
+ 0x1D2000001D246,
),
- 'Han': (
- 0x2e8000002e9a,
- 0x2e9b00002ef4,
- 0x2f0000002fd6,
+ "Han": (
+ 0x2E8000002E9A,
+ 0x2E9B00002EF4,
+ 0x2F0000002FD6,
0x300500003006,
0x300700003008,
- 0x30210000302a,
- 0x30380000303c,
- 0x340000004dc0,
- 0x4e000000a000,
- 0xf9000000fa6e,
- 0xfa700000fada,
- 0x16fe200016fe4,
- 0x16ff000016ff2,
- 0x200000002a6e0,
- 0x2a7000002b73a,
- 0x2b7400002b81e,
- 0x2b8200002cea2,
- 0x2ceb00002ebe1,
- 0x2ebf00002ee5e,
- 0x2f8000002fa1e,
- 0x300000003134b,
- 0x31350000323b0,
+ 0x30210000302A,
+ 0x30380000303C,
+ 0x340000004DC0,
+ 0x4E000000A000,
+ 0xF9000000FA6E,
+ 0xFA700000FADA,
+ 0x16FE200016FE4,
+ 0x16FF000016FF2,
+ 0x200000002A6E0,
+ 0x2A7000002B73A,
+ 0x2B7400002B81E,
+ 0x2B8200002CEA2,
+ 0x2CEB00002EBE1,
+ 0x2EBF00002EE5E,
+ 0x2F8000002FA1E,
+ 0x300000003134B,
+ 0x31350000323B0,
),
- 'Hebrew': (
- 0x591000005c8,
- 0x5d0000005eb,
- 0x5ef000005f5,
- 0xfb1d0000fb37,
- 0xfb380000fb3d,
- 0xfb3e0000fb3f,
- 0xfb400000fb42,
- 0xfb430000fb45,
- 0xfb460000fb50,
+ "Hebrew": (
+ 0x591000005C8,
+ 0x5D0000005EB,
+ 0x5EF000005F5,
+ 0xFB1D0000FB37,
+ 0xFB380000FB3D,
+ 0xFB3E0000FB3F,
+ 0xFB400000FB42,
+ 0xFB430000FB45,
+ 0xFB460000FB50,
),
- 'Hiragana': (
+ "Hiragana": (
0x304100003097,
- 0x309d000030a0,
- 0x1b0010001b120,
- 0x1b1320001b133,
- 0x1b1500001b153,
- 0x1f2000001f201,
+ 0x309D000030A0,
+ 0x1B0010001B120,
+ 0x1B1320001B133,
+ 0x1B1500001B153,
+ 0x1F2000001F201,
),
- 'Katakana': (
- 0x30a1000030fb,
- 0x30fd00003100,
- 0x31f000003200,
- 0x32d0000032ff,
+ "Katakana": (
+ 0x30A1000030FB,
+ 0x30FD00003100,
+ 0x31F000003200,
+ 0x32D0000032FF,
0x330000003358,
- 0xff660000ff70,
- 0xff710000ff9e,
- 0x1aff00001aff4,
- 0x1aff50001affc,
- 0x1affd0001afff,
- 0x1b0000001b001,
- 0x1b1200001b123,
- 0x1b1550001b156,
- 0x1b1640001b168,
+ 0xFF660000FF70,
+ 0xFF710000FF9E,
+ 0x1AFF00001AFF4,
+ 0x1AFF50001AFFC,
+ 0x1AFFD0001AFFF,
+ 0x1B0000001B001,
+ 0x1B1200001B123,
+ 0x1B1550001B156,
+ 0x1B1640001B168,
),
}
joining_types = {
- 0xad: 84,
+ 0xAD: 84,
0x300: 84,
0x301: 84,
0x302: 84,
@@ -112,12 +112,12 @@ joining_types = {
0x307: 84,
0x308: 84,
0x309: 84,
- 0x30a: 84,
- 0x30b: 84,
- 0x30c: 84,
- 0x30d: 84,
- 0x30e: 84,
- 0x30f: 84,
+ 0x30A: 84,
+ 0x30B: 84,
+ 0x30C: 84,
+ 0x30D: 84,
+ 0x30E: 84,
+ 0x30F: 84,
0x310: 84,
0x311: 84,
0x312: 84,
@@ -128,12 +128,12 @@ joining_types = {
0x317: 84,
0x318: 84,
0x319: 84,
- 0x31a: 84,
- 0x31b: 84,
- 0x31c: 84,
- 0x31d: 84,
- 0x31e: 84,
- 0x31f: 84,
+ 0x31A: 84,
+ 0x31B: 84,
+ 0x31C: 84,
+ 0x31D: 84,
+ 0x31E: 84,
+ 0x31F: 84,
0x320: 84,
0x321: 84,
0x322: 84,
@@ -144,12 +144,12 @@ joining_types = {
0x327: 84,
0x328: 84,
0x329: 84,
- 0x32a: 84,
- 0x32b: 84,
- 0x32c: 84,
- 0x32d: 84,
- 0x32e: 84,
- 0x32f: 84,
+ 0x32A: 84,
+ 0x32B: 84,
+ 0x32C: 84,
+ 0x32D: 84,
+ 0x32E: 84,
+ 0x32F: 84,
0x330: 84,
0x331: 84,
0x332: 84,
@@ -160,12 +160,12 @@ joining_types = {
0x337: 84,
0x338: 84,
0x339: 84,
- 0x33a: 84,
- 0x33b: 84,
- 0x33c: 84,
- 0x33d: 84,
- 0x33e: 84,
- 0x33f: 84,
+ 0x33A: 84,
+ 0x33B: 84,
+ 0x33C: 84,
+ 0x33D: 84,
+ 0x33E: 84,
+ 0x33F: 84,
0x340: 84,
0x341: 84,
0x342: 84,
@@ -176,12 +176,12 @@ joining_types = {
0x347: 84,
0x348: 84,
0x349: 84,
- 0x34a: 84,
- 0x34b: 84,
- 0x34c: 84,
- 0x34d: 84,
- 0x34e: 84,
- 0x34f: 84,
+ 0x34A: 84,
+ 0x34B: 84,
+ 0x34C: 84,
+ 0x34D: 84,
+ 0x34E: 84,
+ 0x34F: 84,
0x350: 84,
0x351: 84,
0x352: 84,
@@ -192,12 +192,12 @@ joining_types = {
0x357: 84,
0x358: 84,
0x359: 84,
- 0x35a: 84,
- 0x35b: 84,
- 0x35c: 84,
- 0x35d: 84,
- 0x35e: 84,
- 0x35f: 84,
+ 0x35A: 84,
+ 0x35B: 84,
+ 0x35C: 84,
+ 0x35D: 84,
+ 0x35E: 84,
+ 0x35F: 84,
0x360: 84,
0x361: 84,
0x362: 84,
@@ -208,12 +208,12 @@ joining_types = {
0x367: 84,
0x368: 84,
0x369: 84,
- 0x36a: 84,
- 0x36b: 84,
- 0x36c: 84,
- 0x36d: 84,
- 0x36e: 84,
- 0x36f: 84,
+ 0x36A: 84,
+ 0x36B: 84,
+ 0x36C: 84,
+ 0x36D: 84,
+ 0x36E: 84,
+ 0x36F: 84,
0x483: 84,
0x484: 84,
0x485: 84,
@@ -230,48 +230,48 @@ joining_types = {
0x597: 84,
0x598: 84,
0x599: 84,
- 0x59a: 84,
- 0x59b: 84,
- 0x59c: 84,
- 0x59d: 84,
- 0x59e: 84,
- 0x59f: 84,
- 0x5a0: 84,
- 0x5a1: 84,
- 0x5a2: 84,
- 0x5a3: 84,
- 0x5a4: 84,
- 0x5a5: 84,
- 0x5a6: 84,
- 0x5a7: 84,
- 0x5a8: 84,
- 0x5a9: 84,
- 0x5aa: 84,
- 0x5ab: 84,
- 0x5ac: 84,
- 0x5ad: 84,
- 0x5ae: 84,
- 0x5af: 84,
- 0x5b0: 84,
- 0x5b1: 84,
- 0x5b2: 84,
- 0x5b3: 84,
- 0x5b4: 84,
- 0x5b5: 84,
- 0x5b6: 84,
- 0x5b7: 84,
- 0x5b8: 84,
- 0x5b9: 84,
- 0x5ba: 84,
- 0x5bb: 84,
- 0x5bc: 84,
- 0x5bd: 84,
- 0x5bf: 84,
- 0x5c1: 84,
- 0x5c2: 84,
- 0x5c4: 84,
- 0x5c5: 84,
- 0x5c7: 84,
+ 0x59A: 84,
+ 0x59B: 84,
+ 0x59C: 84,
+ 0x59D: 84,
+ 0x59E: 84,
+ 0x59F: 84,
+ 0x5A0: 84,
+ 0x5A1: 84,
+ 0x5A2: 84,
+ 0x5A3: 84,
+ 0x5A4: 84,
+ 0x5A5: 84,
+ 0x5A6: 84,
+ 0x5A7: 84,
+ 0x5A8: 84,
+ 0x5A9: 84,
+ 0x5AA: 84,
+ 0x5AB: 84,
+ 0x5AC: 84,
+ 0x5AD: 84,
+ 0x5AE: 84,
+ 0x5AF: 84,
+ 0x5B0: 84,
+ 0x5B1: 84,
+ 0x5B2: 84,
+ 0x5B3: 84,
+ 0x5B4: 84,
+ 0x5B5: 84,
+ 0x5B6: 84,
+ 0x5B7: 84,
+ 0x5B8: 84,
+ 0x5B9: 84,
+ 0x5BA: 84,
+ 0x5BB: 84,
+ 0x5BC: 84,
+ 0x5BD: 84,
+ 0x5BF: 84,
+ 0x5C1: 84,
+ 0x5C2: 84,
+ 0x5C4: 84,
+ 0x5C5: 84,
+ 0x5C7: 84,
0x610: 84,
0x611: 84,
0x612: 84,
@@ -282,8 +282,8 @@ joining_types = {
0x617: 84,
0x618: 84,
0x619: 84,
- 0x61a: 84,
- 0x61c: 84,
+ 0x61A: 84,
+ 0x61C: 84,
0x620: 68,
0x622: 82,
0x623: 82,
@@ -293,12 +293,12 @@ joining_types = {
0x627: 82,
0x628: 68,
0x629: 82,
- 0x62a: 68,
- 0x62b: 68,
- 0x62c: 68,
- 0x62d: 68,
- 0x62e: 68,
- 0x62f: 82,
+ 0x62A: 68,
+ 0x62B: 68,
+ 0x62C: 68,
+ 0x62D: 68,
+ 0x62E: 68,
+ 0x62F: 82,
0x630: 82,
0x631: 82,
0x632: 82,
@@ -309,12 +309,12 @@ joining_types = {
0x637: 68,
0x638: 68,
0x639: 68,
- 0x63a: 68,
- 0x63b: 68,
- 0x63c: 68,
- 0x63d: 68,
- 0x63e: 68,
- 0x63f: 68,
+ 0x63A: 68,
+ 0x63B: 68,
+ 0x63C: 68,
+ 0x63D: 68,
+ 0x63E: 68,
+ 0x63F: 68,
0x640: 67,
0x641: 68,
0x642: 68,
@@ -325,12 +325,12 @@ joining_types = {
0x647: 68,
0x648: 82,
0x649: 68,
- 0x64a: 68,
- 0x64b: 84,
- 0x64c: 84,
- 0x64d: 84,
- 0x64e: 84,
- 0x64f: 84,
+ 0x64A: 68,
+ 0x64B: 84,
+ 0x64C: 84,
+ 0x64D: 84,
+ 0x64E: 84,
+ 0x64F: 84,
0x650: 84,
0x651: 84,
0x652: 84,
@@ -341,14 +341,14 @@ joining_types = {
0x657: 84,
0x658: 84,
0x659: 84,
- 0x65a: 84,
- 0x65b: 84,
- 0x65c: 84,
- 0x65d: 84,
- 0x65e: 84,
- 0x65f: 84,
- 0x66e: 68,
- 0x66f: 68,
+ 0x65A: 84,
+ 0x65B: 84,
+ 0x65C: 84,
+ 0x65D: 84,
+ 0x65E: 84,
+ 0x65F: 84,
+ 0x66E: 68,
+ 0x66F: 68,
0x670: 84,
0x671: 82,
0x672: 82,
@@ -358,12 +358,12 @@ joining_types = {
0x677: 82,
0x678: 68,
0x679: 68,
- 0x67a: 68,
- 0x67b: 68,
- 0x67c: 68,
- 0x67d: 68,
- 0x67e: 68,
- 0x67f: 68,
+ 0x67A: 68,
+ 0x67B: 68,
+ 0x67C: 68,
+ 0x67D: 68,
+ 0x67E: 68,
+ 0x67F: 68,
0x680: 68,
0x681: 68,
0x682: 68,
@@ -374,12 +374,12 @@ joining_types = {
0x687: 68,
0x688: 82,
0x689: 82,
- 0x68a: 82,
- 0x68b: 82,
- 0x68c: 82,
- 0x68d: 82,
- 0x68e: 82,
- 0x68f: 82,
+ 0x68A: 82,
+ 0x68B: 82,
+ 0x68C: 82,
+ 0x68D: 82,
+ 0x68E: 82,
+ 0x68F: 82,
0x690: 82,
0x691: 82,
0x692: 82,
@@ -390,91 +390,91 @@ joining_types = {
0x697: 82,
0x698: 82,
0x699: 82,
- 0x69a: 68,
- 0x69b: 68,
- 0x69c: 68,
- 0x69d: 68,
- 0x69e: 68,
- 0x69f: 68,
- 0x6a0: 68,
- 0x6a1: 68,
- 0x6a2: 68,
- 0x6a3: 68,
- 0x6a4: 68,
- 0x6a5: 68,
- 0x6a6: 68,
- 0x6a7: 68,
- 0x6a8: 68,
- 0x6a9: 68,
- 0x6aa: 68,
- 0x6ab: 68,
- 0x6ac: 68,
- 0x6ad: 68,
- 0x6ae: 68,
- 0x6af: 68,
- 0x6b0: 68,
- 0x6b1: 68,
- 0x6b2: 68,
- 0x6b3: 68,
- 0x6b4: 68,
- 0x6b5: 68,
- 0x6b6: 68,
- 0x6b7: 68,
- 0x6b8: 68,
- 0x6b9: 68,
- 0x6ba: 68,
- 0x6bb: 68,
- 0x6bc: 68,
- 0x6bd: 68,
- 0x6be: 68,
- 0x6bf: 68,
- 0x6c0: 82,
- 0x6c1: 68,
- 0x6c2: 68,
- 0x6c3: 82,
- 0x6c4: 82,
- 0x6c5: 82,
- 0x6c6: 82,
- 0x6c7: 82,
- 0x6c8: 82,
- 0x6c9: 82,
- 0x6ca: 82,
- 0x6cb: 82,
- 0x6cc: 68,
- 0x6cd: 82,
- 0x6ce: 68,
- 0x6cf: 82,
- 0x6d0: 68,
- 0x6d1: 68,
- 0x6d2: 82,
- 0x6d3: 82,
- 0x6d5: 82,
- 0x6d6: 84,
- 0x6d7: 84,
- 0x6d8: 84,
- 0x6d9: 84,
- 0x6da: 84,
- 0x6db: 84,
- 0x6dc: 84,
- 0x6df: 84,
- 0x6e0: 84,
- 0x6e1: 84,
- 0x6e2: 84,
- 0x6e3: 84,
- 0x6e4: 84,
- 0x6e7: 84,
- 0x6e8: 84,
- 0x6ea: 84,
- 0x6eb: 84,
- 0x6ec: 84,
- 0x6ed: 84,
- 0x6ee: 82,
- 0x6ef: 82,
- 0x6fa: 68,
- 0x6fb: 68,
- 0x6fc: 68,
- 0x6ff: 68,
- 0x70f: 84,
+ 0x69A: 68,
+ 0x69B: 68,
+ 0x69C: 68,
+ 0x69D: 68,
+ 0x69E: 68,
+ 0x69F: 68,
+ 0x6A0: 68,
+ 0x6A1: 68,
+ 0x6A2: 68,
+ 0x6A3: 68,
+ 0x6A4: 68,
+ 0x6A5: 68,
+ 0x6A6: 68,
+ 0x6A7: 68,
+ 0x6A8: 68,
+ 0x6A9: 68,
+ 0x6AA: 68,
+ 0x6AB: 68,
+ 0x6AC: 68,
+ 0x6AD: 68,
+ 0x6AE: 68,
+ 0x6AF: 68,
+ 0x6B0: 68,
+ 0x6B1: 68,
+ 0x6B2: 68,
+ 0x6B3: 68,
+ 0x6B4: 68,
+ 0x6B5: 68,
+ 0x6B6: 68,
+ 0x6B7: 68,
+ 0x6B8: 68,
+ 0x6B9: 68,
+ 0x6BA: 68,
+ 0x6BB: 68,
+ 0x6BC: 68,
+ 0x6BD: 68,
+ 0x6BE: 68,
+ 0x6BF: 68,
+ 0x6C0: 82,
+ 0x6C1: 68,
+ 0x6C2: 68,
+ 0x6C3: 82,
+ 0x6C4: 82,
+ 0x6C5: 82,
+ 0x6C6: 82,
+ 0x6C7: 82,
+ 0x6C8: 82,
+ 0x6C9: 82,
+ 0x6CA: 82,
+ 0x6CB: 82,
+ 0x6CC: 68,
+ 0x6CD: 82,
+ 0x6CE: 68,
+ 0x6CF: 82,
+ 0x6D0: 68,
+ 0x6D1: 68,
+ 0x6D2: 82,
+ 0x6D3: 82,
+ 0x6D5: 82,
+ 0x6D6: 84,
+ 0x6D7: 84,
+ 0x6D8: 84,
+ 0x6D9: 84,
+ 0x6DA: 84,
+ 0x6DB: 84,
+ 0x6DC: 84,
+ 0x6DF: 84,
+ 0x6E0: 84,
+ 0x6E1: 84,
+ 0x6E2: 84,
+ 0x6E3: 84,
+ 0x6E4: 84,
+ 0x6E7: 84,
+ 0x6E8: 84,
+ 0x6EA: 84,
+ 0x6EB: 84,
+ 0x6EC: 84,
+ 0x6ED: 84,
+ 0x6EE: 82,
+ 0x6EF: 82,
+ 0x6FA: 68,
+ 0x6FB: 68,
+ 0x6FC: 68,
+ 0x6FF: 68,
+ 0x70F: 84,
0x710: 82,
0x711: 84,
0x712: 68,
@@ -485,12 +485,12 @@ joining_types = {
0x717: 82,
0x718: 82,
0x719: 82,
- 0x71a: 68,
- 0x71b: 68,
- 0x71c: 68,
- 0x71d: 68,
- 0x71e: 82,
- 0x71f: 68,
+ 0x71A: 68,
+ 0x71B: 68,
+ 0x71C: 68,
+ 0x71D: 68,
+ 0x71E: 82,
+ 0x71F: 68,
0x720: 68,
0x721: 68,
0x722: 68,
@@ -501,12 +501,12 @@ joining_types = {
0x727: 68,
0x728: 82,
0x729: 68,
- 0x72a: 82,
- 0x72b: 68,
- 0x72c: 82,
- 0x72d: 68,
- 0x72e: 68,
- 0x72f: 82,
+ 0x72A: 82,
+ 0x72B: 68,
+ 0x72C: 82,
+ 0x72D: 68,
+ 0x72E: 68,
+ 0x72F: 82,
0x730: 84,
0x731: 84,
0x732: 84,
@@ -517,12 +517,12 @@ joining_types = {
0x737: 84,
0x738: 84,
0x739: 84,
- 0x73a: 84,
- 0x73b: 84,
- 0x73c: 84,
- 0x73d: 84,
- 0x73e: 84,
- 0x73f: 84,
+ 0x73A: 84,
+ 0x73B: 84,
+ 0x73C: 84,
+ 0x73D: 84,
+ 0x73E: 84,
+ 0x73F: 84,
0x740: 84,
0x741: 84,
0x742: 84,
@@ -533,10 +533,10 @@ joining_types = {
0x747: 84,
0x748: 84,
0x749: 84,
- 0x74a: 84,
- 0x74d: 82,
- 0x74e: 68,
- 0x74f: 68,
+ 0x74A: 84,
+ 0x74D: 82,
+ 0x74E: 68,
+ 0x74F: 68,
0x750: 68,
0x751: 68,
0x752: 68,
@@ -547,12 +547,12 @@ joining_types = {
0x757: 68,
0x758: 68,
0x759: 82,
- 0x75a: 82,
- 0x75b: 82,
- 0x75c: 68,
- 0x75d: 68,
- 0x75e: 68,
- 0x75f: 68,
+ 0x75A: 82,
+ 0x75B: 82,
+ 0x75C: 68,
+ 0x75D: 68,
+ 0x75E: 68,
+ 0x75F: 68,
0x760: 68,
0x761: 68,
0x762: 68,
@@ -563,12 +563,12 @@ joining_types = {
0x767: 68,
0x768: 68,
0x769: 68,
- 0x76a: 68,
- 0x76b: 82,
- 0x76c: 82,
- 0x76d: 68,
- 0x76e: 68,
- 0x76f: 68,
+ 0x76A: 68,
+ 0x76B: 82,
+ 0x76C: 82,
+ 0x76D: 68,
+ 0x76E: 68,
+ 0x76F: 68,
0x770: 68,
0x771: 82,
0x772: 68,
@@ -579,76 +579,76 @@ joining_types = {
0x777: 68,
0x778: 82,
0x779: 82,
- 0x77a: 68,
- 0x77b: 68,
- 0x77c: 68,
- 0x77d: 68,
- 0x77e: 68,
- 0x77f: 68,
- 0x7a6: 84,
- 0x7a7: 84,
- 0x7a8: 84,
- 0x7a9: 84,
- 0x7aa: 84,
- 0x7ab: 84,
- 0x7ac: 84,
- 0x7ad: 84,
- 0x7ae: 84,
- 0x7af: 84,
- 0x7b0: 84,
- 0x7ca: 68,
- 0x7cb: 68,
- 0x7cc: 68,
- 0x7cd: 68,
- 0x7ce: 68,
- 0x7cf: 68,
- 0x7d0: 68,
- 0x7d1: 68,
- 0x7d2: 68,
- 0x7d3: 68,
- 0x7d4: 68,
- 0x7d5: 68,
- 0x7d6: 68,
- 0x7d7: 68,
- 0x7d8: 68,
- 0x7d9: 68,
- 0x7da: 68,
- 0x7db: 68,
- 0x7dc: 68,
- 0x7dd: 68,
- 0x7de: 68,
- 0x7df: 68,
- 0x7e0: 68,
- 0x7e1: 68,
- 0x7e2: 68,
- 0x7e3: 68,
- 0x7e4: 68,
- 0x7e5: 68,
- 0x7e6: 68,
- 0x7e7: 68,
- 0x7e8: 68,
- 0x7e9: 68,
- 0x7ea: 68,
- 0x7eb: 84,
- 0x7ec: 84,
- 0x7ed: 84,
- 0x7ee: 84,
- 0x7ef: 84,
- 0x7f0: 84,
- 0x7f1: 84,
- 0x7f2: 84,
- 0x7f3: 84,
- 0x7fa: 67,
- 0x7fd: 84,
+ 0x77A: 68,
+ 0x77B: 68,
+ 0x77C: 68,
+ 0x77D: 68,
+ 0x77E: 68,
+ 0x77F: 68,
+ 0x7A6: 84,
+ 0x7A7: 84,
+ 0x7A8: 84,
+ 0x7A9: 84,
+ 0x7AA: 84,
+ 0x7AB: 84,
+ 0x7AC: 84,
+ 0x7AD: 84,
+ 0x7AE: 84,
+ 0x7AF: 84,
+ 0x7B0: 84,
+ 0x7CA: 68,
+ 0x7CB: 68,
+ 0x7CC: 68,
+ 0x7CD: 68,
+ 0x7CE: 68,
+ 0x7CF: 68,
+ 0x7D0: 68,
+ 0x7D1: 68,
+ 0x7D2: 68,
+ 0x7D3: 68,
+ 0x7D4: 68,
+ 0x7D5: 68,
+ 0x7D6: 68,
+ 0x7D7: 68,
+ 0x7D8: 68,
+ 0x7D9: 68,
+ 0x7DA: 68,
+ 0x7DB: 68,
+ 0x7DC: 68,
+ 0x7DD: 68,
+ 0x7DE: 68,
+ 0x7DF: 68,
+ 0x7E0: 68,
+ 0x7E1: 68,
+ 0x7E2: 68,
+ 0x7E3: 68,
+ 0x7E4: 68,
+ 0x7E5: 68,
+ 0x7E6: 68,
+ 0x7E7: 68,
+ 0x7E8: 68,
+ 0x7E9: 68,
+ 0x7EA: 68,
+ 0x7EB: 84,
+ 0x7EC: 84,
+ 0x7ED: 84,
+ 0x7EE: 84,
+ 0x7EF: 84,
+ 0x7F0: 84,
+ 0x7F1: 84,
+ 0x7F2: 84,
+ 0x7F3: 84,
+ 0x7FA: 67,
+ 0x7FD: 84,
0x816: 84,
0x817: 84,
0x818: 84,
0x819: 84,
- 0x81b: 84,
- 0x81c: 84,
- 0x81d: 84,
- 0x81e: 84,
- 0x81f: 84,
+ 0x81B: 84,
+ 0x81C: 84,
+ 0x81D: 84,
+ 0x81E: 84,
+ 0x81F: 84,
0x820: 84,
0x821: 84,
0x822: 84,
@@ -657,10 +657,10 @@ joining_types = {
0x826: 84,
0x827: 84,
0x829: 84,
- 0x82a: 84,
- 0x82b: 84,
- 0x82c: 84,
- 0x82d: 84,
+ 0x82A: 84,
+ 0x82B: 84,
+ 0x82C: 84,
+ 0x82D: 84,
0x840: 82,
0x841: 68,
0x842: 68,
@@ -671,12 +671,12 @@ joining_types = {
0x847: 82,
0x848: 68,
0x849: 82,
- 0x84a: 68,
- 0x84b: 68,
- 0x84c: 68,
- 0x84d: 68,
- 0x84e: 68,
- 0x84f: 68,
+ 0x84A: 68,
+ 0x84B: 68,
+ 0x84C: 68,
+ 0x84D: 68,
+ 0x84E: 68,
+ 0x84F: 68,
0x850: 68,
0x851: 68,
0x852: 68,
@@ -687,8 +687,8 @@ joining_types = {
0x857: 82,
0x858: 82,
0x859: 84,
- 0x85a: 84,
- 0x85b: 84,
+ 0x85A: 84,
+ 0x85B: 84,
0x860: 68,
0x862: 68,
0x863: 68,
@@ -697,7 +697,7 @@ joining_types = {
0x867: 82,
0x868: 68,
0x869: 82,
- 0x86a: 82,
+ 0x86A: 82,
0x870: 82,
0x871: 82,
0x872: 82,
@@ -708,12 +708,12 @@ joining_types = {
0x877: 82,
0x878: 82,
0x879: 82,
- 0x87a: 82,
- 0x87b: 82,
- 0x87c: 82,
- 0x87d: 82,
- 0x87e: 82,
- 0x87f: 82,
+ 0x87A: 82,
+ 0x87B: 82,
+ 0x87C: 82,
+ 0x87D: 82,
+ 0x87E: 82,
+ 0x87F: 82,
0x880: 82,
0x881: 82,
0x882: 82,
@@ -722,117 +722,117 @@ joining_types = {
0x885: 67,
0x886: 68,
0x889: 68,
- 0x88a: 68,
- 0x88b: 68,
- 0x88c: 68,
- 0x88d: 68,
- 0x88e: 82,
+ 0x88A: 68,
+ 0x88B: 68,
+ 0x88C: 68,
+ 0x88D: 68,
+ 0x88E: 82,
0x898: 84,
0x899: 84,
- 0x89a: 84,
- 0x89b: 84,
- 0x89c: 84,
- 0x89d: 84,
- 0x89e: 84,
- 0x89f: 84,
- 0x8a0: 68,
- 0x8a1: 68,
- 0x8a2: 68,
- 0x8a3: 68,
- 0x8a4: 68,
- 0x8a5: 68,
- 0x8a6: 68,
- 0x8a7: 68,
- 0x8a8: 68,
- 0x8a9: 68,
- 0x8aa: 82,
- 0x8ab: 82,
- 0x8ac: 82,
- 0x8ae: 82,
- 0x8af: 68,
- 0x8b0: 68,
- 0x8b1: 82,
- 0x8b2: 82,
- 0x8b3: 68,
- 0x8b4: 68,
- 0x8b5: 68,
- 0x8b6: 68,
- 0x8b7: 68,
- 0x8b8: 68,
- 0x8b9: 82,
- 0x8ba: 68,
- 0x8bb: 68,
- 0x8bc: 68,
- 0x8bd: 68,
- 0x8be: 68,
- 0x8bf: 68,
- 0x8c0: 68,
- 0x8c1: 68,
- 0x8c2: 68,
- 0x8c3: 68,
- 0x8c4: 68,
- 0x8c5: 68,
- 0x8c6: 68,
- 0x8c7: 68,
- 0x8c8: 68,
- 0x8ca: 84,
- 0x8cb: 84,
- 0x8cc: 84,
- 0x8cd: 84,
- 0x8ce: 84,
- 0x8cf: 84,
- 0x8d0: 84,
- 0x8d1: 84,
- 0x8d2: 84,
- 0x8d3: 84,
- 0x8d4: 84,
- 0x8d5: 84,
- 0x8d6: 84,
- 0x8d7: 84,
- 0x8d8: 84,
- 0x8d9: 84,
- 0x8da: 84,
- 0x8db: 84,
- 0x8dc: 84,
- 0x8dd: 84,
- 0x8de: 84,
- 0x8df: 84,
- 0x8e0: 84,
- 0x8e1: 84,
- 0x8e3: 84,
- 0x8e4: 84,
- 0x8e5: 84,
- 0x8e6: 84,
- 0x8e7: 84,
- 0x8e8: 84,
- 0x8e9: 84,
- 0x8ea: 84,
- 0x8eb: 84,
- 0x8ec: 84,
- 0x8ed: 84,
- 0x8ee: 84,
- 0x8ef: 84,
- 0x8f0: 84,
- 0x8f1: 84,
- 0x8f2: 84,
- 0x8f3: 84,
- 0x8f4: 84,
- 0x8f5: 84,
- 0x8f6: 84,
- 0x8f7: 84,
- 0x8f8: 84,
- 0x8f9: 84,
- 0x8fa: 84,
- 0x8fb: 84,
- 0x8fc: 84,
- 0x8fd: 84,
- 0x8fe: 84,
- 0x8ff: 84,
+ 0x89A: 84,
+ 0x89B: 84,
+ 0x89C: 84,
+ 0x89D: 84,
+ 0x89E: 84,
+ 0x89F: 84,
+ 0x8A0: 68,
+ 0x8A1: 68,
+ 0x8A2: 68,
+ 0x8A3: 68,
+ 0x8A4: 68,
+ 0x8A5: 68,
+ 0x8A6: 68,
+ 0x8A7: 68,
+ 0x8A8: 68,
+ 0x8A9: 68,
+ 0x8AA: 82,
+ 0x8AB: 82,
+ 0x8AC: 82,
+ 0x8AE: 82,
+ 0x8AF: 68,
+ 0x8B0: 68,
+ 0x8B1: 82,
+ 0x8B2: 82,
+ 0x8B3: 68,
+ 0x8B4: 68,
+ 0x8B5: 68,
+ 0x8B6: 68,
+ 0x8B7: 68,
+ 0x8B8: 68,
+ 0x8B9: 82,
+ 0x8BA: 68,
+ 0x8BB: 68,
+ 0x8BC: 68,
+ 0x8BD: 68,
+ 0x8BE: 68,
+ 0x8BF: 68,
+ 0x8C0: 68,
+ 0x8C1: 68,
+ 0x8C2: 68,
+ 0x8C3: 68,
+ 0x8C4: 68,
+ 0x8C5: 68,
+ 0x8C6: 68,
+ 0x8C7: 68,
+ 0x8C8: 68,
+ 0x8CA: 84,
+ 0x8CB: 84,
+ 0x8CC: 84,
+ 0x8CD: 84,
+ 0x8CE: 84,
+ 0x8CF: 84,
+ 0x8D0: 84,
+ 0x8D1: 84,
+ 0x8D2: 84,
+ 0x8D3: 84,
+ 0x8D4: 84,
+ 0x8D5: 84,
+ 0x8D6: 84,
+ 0x8D7: 84,
+ 0x8D8: 84,
+ 0x8D9: 84,
+ 0x8DA: 84,
+ 0x8DB: 84,
+ 0x8DC: 84,
+ 0x8DD: 84,
+ 0x8DE: 84,
+ 0x8DF: 84,
+ 0x8E0: 84,
+ 0x8E1: 84,
+ 0x8E3: 84,
+ 0x8E4: 84,
+ 0x8E5: 84,
+ 0x8E6: 84,
+ 0x8E7: 84,
+ 0x8E8: 84,
+ 0x8E9: 84,
+ 0x8EA: 84,
+ 0x8EB: 84,
+ 0x8EC: 84,
+ 0x8ED: 84,
+ 0x8EE: 84,
+ 0x8EF: 84,
+ 0x8F0: 84,
+ 0x8F1: 84,
+ 0x8F2: 84,
+ 0x8F3: 84,
+ 0x8F4: 84,
+ 0x8F5: 84,
+ 0x8F6: 84,
+ 0x8F7: 84,
+ 0x8F8: 84,
+ 0x8F9: 84,
+ 0x8FA: 84,
+ 0x8FB: 84,
+ 0x8FC: 84,
+ 0x8FD: 84,
+ 0x8FE: 84,
+ 0x8FF: 84,
0x900: 84,
0x901: 84,
0x902: 84,
- 0x93a: 84,
- 0x93c: 84,
+ 0x93A: 84,
+ 0x93C: 84,
0x941: 84,
0x942: 84,
0x943: 84,
@@ -841,7 +841,7 @@ joining_types = {
0x946: 84,
0x947: 84,
0x948: 84,
- 0x94d: 84,
+ 0x94D: 84,
0x951: 84,
0x952: 84,
0x953: 84,
@@ -852,215 +852,215 @@ joining_types = {
0x962: 84,
0x963: 84,
0x981: 84,
- 0x9bc: 84,
- 0x9c1: 84,
- 0x9c2: 84,
- 0x9c3: 84,
- 0x9c4: 84,
- 0x9cd: 84,
- 0x9e2: 84,
- 0x9e3: 84,
- 0x9fe: 84,
- 0xa01: 84,
- 0xa02: 84,
- 0xa3c: 84,
- 0xa41: 84,
- 0xa42: 84,
- 0xa47: 84,
- 0xa48: 84,
- 0xa4b: 84,
- 0xa4c: 84,
- 0xa4d: 84,
- 0xa51: 84,
- 0xa70: 84,
- 0xa71: 84,
- 0xa75: 84,
- 0xa81: 84,
- 0xa82: 84,
- 0xabc: 84,
- 0xac1: 84,
- 0xac2: 84,
- 0xac3: 84,
- 0xac4: 84,
- 0xac5: 84,
- 0xac7: 84,
- 0xac8: 84,
- 0xacd: 84,
- 0xae2: 84,
- 0xae3: 84,
- 0xafa: 84,
- 0xafb: 84,
- 0xafc: 84,
- 0xafd: 84,
- 0xafe: 84,
- 0xaff: 84,
- 0xb01: 84,
- 0xb3c: 84,
- 0xb3f: 84,
- 0xb41: 84,
- 0xb42: 84,
- 0xb43: 84,
- 0xb44: 84,
- 0xb4d: 84,
- 0xb55: 84,
- 0xb56: 84,
- 0xb62: 84,
- 0xb63: 84,
- 0xb82: 84,
- 0xbc0: 84,
- 0xbcd: 84,
- 0xc00: 84,
- 0xc04: 84,
- 0xc3c: 84,
- 0xc3e: 84,
- 0xc3f: 84,
- 0xc40: 84,
- 0xc46: 84,
- 0xc47: 84,
- 0xc48: 84,
- 0xc4a: 84,
- 0xc4b: 84,
- 0xc4c: 84,
- 0xc4d: 84,
- 0xc55: 84,
- 0xc56: 84,
- 0xc62: 84,
- 0xc63: 84,
- 0xc81: 84,
- 0xcbc: 84,
- 0xcbf: 84,
- 0xcc6: 84,
- 0xccc: 84,
- 0xccd: 84,
- 0xce2: 84,
- 0xce3: 84,
- 0xd00: 84,
- 0xd01: 84,
- 0xd3b: 84,
- 0xd3c: 84,
- 0xd41: 84,
- 0xd42: 84,
- 0xd43: 84,
- 0xd44: 84,
- 0xd4d: 84,
- 0xd62: 84,
- 0xd63: 84,
- 0xd81: 84,
- 0xdca: 84,
- 0xdd2: 84,
- 0xdd3: 84,
- 0xdd4: 84,
- 0xdd6: 84,
- 0xe31: 84,
- 0xe34: 84,
- 0xe35: 84,
- 0xe36: 84,
- 0xe37: 84,
- 0xe38: 84,
- 0xe39: 84,
- 0xe3a: 84,
- 0xe47: 84,
- 0xe48: 84,
- 0xe49: 84,
- 0xe4a: 84,
- 0xe4b: 84,
- 0xe4c: 84,
- 0xe4d: 84,
- 0xe4e: 84,
- 0xeb1: 84,
- 0xeb4: 84,
- 0xeb5: 84,
- 0xeb6: 84,
- 0xeb7: 84,
- 0xeb8: 84,
- 0xeb9: 84,
- 0xeba: 84,
- 0xebb: 84,
- 0xebc: 84,
- 0xec8: 84,
- 0xec9: 84,
- 0xeca: 84,
- 0xecb: 84,
- 0xecc: 84,
- 0xecd: 84,
- 0xece: 84,
- 0xf18: 84,
- 0xf19: 84,
- 0xf35: 84,
- 0xf37: 84,
- 0xf39: 84,
- 0xf71: 84,
- 0xf72: 84,
- 0xf73: 84,
- 0xf74: 84,
- 0xf75: 84,
- 0xf76: 84,
- 0xf77: 84,
- 0xf78: 84,
- 0xf79: 84,
- 0xf7a: 84,
- 0xf7b: 84,
- 0xf7c: 84,
- 0xf7d: 84,
- 0xf7e: 84,
- 0xf80: 84,
- 0xf81: 84,
- 0xf82: 84,
- 0xf83: 84,
- 0xf84: 84,
- 0xf86: 84,
- 0xf87: 84,
- 0xf8d: 84,
- 0xf8e: 84,
- 0xf8f: 84,
- 0xf90: 84,
- 0xf91: 84,
- 0xf92: 84,
- 0xf93: 84,
- 0xf94: 84,
- 0xf95: 84,
- 0xf96: 84,
- 0xf97: 84,
- 0xf99: 84,
- 0xf9a: 84,
- 0xf9b: 84,
- 0xf9c: 84,
- 0xf9d: 84,
- 0xf9e: 84,
- 0xf9f: 84,
- 0xfa0: 84,
- 0xfa1: 84,
- 0xfa2: 84,
- 0xfa3: 84,
- 0xfa4: 84,
- 0xfa5: 84,
- 0xfa6: 84,
- 0xfa7: 84,
- 0xfa8: 84,
- 0xfa9: 84,
- 0xfaa: 84,
- 0xfab: 84,
- 0xfac: 84,
- 0xfad: 84,
- 0xfae: 84,
- 0xfaf: 84,
- 0xfb0: 84,
- 0xfb1: 84,
- 0xfb2: 84,
- 0xfb3: 84,
- 0xfb4: 84,
- 0xfb5: 84,
- 0xfb6: 84,
- 0xfb7: 84,
- 0xfb8: 84,
- 0xfb9: 84,
- 0xfba: 84,
- 0xfbb: 84,
- 0xfbc: 84,
- 0xfc6: 84,
- 0x102d: 84,
- 0x102e: 84,
- 0x102f: 84,
+ 0x9BC: 84,
+ 0x9C1: 84,
+ 0x9C2: 84,
+ 0x9C3: 84,
+ 0x9C4: 84,
+ 0x9CD: 84,
+ 0x9E2: 84,
+ 0x9E3: 84,
+ 0x9FE: 84,
+ 0xA01: 84,
+ 0xA02: 84,
+ 0xA3C: 84,
+ 0xA41: 84,
+ 0xA42: 84,
+ 0xA47: 84,
+ 0xA48: 84,
+ 0xA4B: 84,
+ 0xA4C: 84,
+ 0xA4D: 84,
+ 0xA51: 84,
+ 0xA70: 84,
+ 0xA71: 84,
+ 0xA75: 84,
+ 0xA81: 84,
+ 0xA82: 84,
+ 0xABC: 84,
+ 0xAC1: 84,
+ 0xAC2: 84,
+ 0xAC3: 84,
+ 0xAC4: 84,
+ 0xAC5: 84,
+ 0xAC7: 84,
+ 0xAC8: 84,
+ 0xACD: 84,
+ 0xAE2: 84,
+ 0xAE3: 84,
+ 0xAFA: 84,
+ 0xAFB: 84,
+ 0xAFC: 84,
+ 0xAFD: 84,
+ 0xAFE: 84,
+ 0xAFF: 84,
+ 0xB01: 84,
+ 0xB3C: 84,
+ 0xB3F: 84,
+ 0xB41: 84,
+ 0xB42: 84,
+ 0xB43: 84,
+ 0xB44: 84,
+ 0xB4D: 84,
+ 0xB55: 84,
+ 0xB56: 84,
+ 0xB62: 84,
+ 0xB63: 84,
+ 0xB82: 84,
+ 0xBC0: 84,
+ 0xBCD: 84,
+ 0xC00: 84,
+ 0xC04: 84,
+ 0xC3C: 84,
+ 0xC3E: 84,
+ 0xC3F: 84,
+ 0xC40: 84,
+ 0xC46: 84,
+ 0xC47: 84,
+ 0xC48: 84,
+ 0xC4A: 84,
+ 0xC4B: 84,
+ 0xC4C: 84,
+ 0xC4D: 84,
+ 0xC55: 84,
+ 0xC56: 84,
+ 0xC62: 84,
+ 0xC63: 84,
+ 0xC81: 84,
+ 0xCBC: 84,
+ 0xCBF: 84,
+ 0xCC6: 84,
+ 0xCCC: 84,
+ 0xCCD: 84,
+ 0xCE2: 84,
+ 0xCE3: 84,
+ 0xD00: 84,
+ 0xD01: 84,
+ 0xD3B: 84,
+ 0xD3C: 84,
+ 0xD41: 84,
+ 0xD42: 84,
+ 0xD43: 84,
+ 0xD44: 84,
+ 0xD4D: 84,
+ 0xD62: 84,
+ 0xD63: 84,
+ 0xD81: 84,
+ 0xDCA: 84,
+ 0xDD2: 84,
+ 0xDD3: 84,
+ 0xDD4: 84,
+ 0xDD6: 84,
+ 0xE31: 84,
+ 0xE34: 84,
+ 0xE35: 84,
+ 0xE36: 84,
+ 0xE37: 84,
+ 0xE38: 84,
+ 0xE39: 84,
+ 0xE3A: 84,
+ 0xE47: 84,
+ 0xE48: 84,
+ 0xE49: 84,
+ 0xE4A: 84,
+ 0xE4B: 84,
+ 0xE4C: 84,
+ 0xE4D: 84,
+ 0xE4E: 84,
+ 0xEB1: 84,
+ 0xEB4: 84,
+ 0xEB5: 84,
+ 0xEB6: 84,
+ 0xEB7: 84,
+ 0xEB8: 84,
+ 0xEB9: 84,
+ 0xEBA: 84,
+ 0xEBB: 84,
+ 0xEBC: 84,
+ 0xEC8: 84,
+ 0xEC9: 84,
+ 0xECA: 84,
+ 0xECB: 84,
+ 0xECC: 84,
+ 0xECD: 84,
+ 0xECE: 84,
+ 0xF18: 84,
+ 0xF19: 84,
+ 0xF35: 84,
+ 0xF37: 84,
+ 0xF39: 84,
+ 0xF71: 84,
+ 0xF72: 84,
+ 0xF73: 84,
+ 0xF74: 84,
+ 0xF75: 84,
+ 0xF76: 84,
+ 0xF77: 84,
+ 0xF78: 84,
+ 0xF79: 84,
+ 0xF7A: 84,
+ 0xF7B: 84,
+ 0xF7C: 84,
+ 0xF7D: 84,
+ 0xF7E: 84,
+ 0xF80: 84,
+ 0xF81: 84,
+ 0xF82: 84,
+ 0xF83: 84,
+ 0xF84: 84,
+ 0xF86: 84,
+ 0xF87: 84,
+ 0xF8D: 84,
+ 0xF8E: 84,
+ 0xF8F: 84,
+ 0xF90: 84,
+ 0xF91: 84,
+ 0xF92: 84,
+ 0xF93: 84,
+ 0xF94: 84,
+ 0xF95: 84,
+ 0xF96: 84,
+ 0xF97: 84,
+ 0xF99: 84,
+ 0xF9A: 84,
+ 0xF9B: 84,
+ 0xF9C: 84,
+ 0xF9D: 84,
+ 0xF9E: 84,
+ 0xF9F: 84,
+ 0xFA0: 84,
+ 0xFA1: 84,
+ 0xFA2: 84,
+ 0xFA3: 84,
+ 0xFA4: 84,
+ 0xFA5: 84,
+ 0xFA6: 84,
+ 0xFA7: 84,
+ 0xFA8: 84,
+ 0xFA9: 84,
+ 0xFAA: 84,
+ 0xFAB: 84,
+ 0xFAC: 84,
+ 0xFAD: 84,
+ 0xFAE: 84,
+ 0xFAF: 84,
+ 0xFB0: 84,
+ 0xFB1: 84,
+ 0xFB2: 84,
+ 0xFB3: 84,
+ 0xFB4: 84,
+ 0xFB5: 84,
+ 0xFB6: 84,
+ 0xFB7: 84,
+ 0xFB8: 84,
+ 0xFB9: 84,
+ 0xFBA: 84,
+ 0xFBB: 84,
+ 0xFBC: 84,
+ 0xFC6: 84,
+ 0x102D: 84,
+ 0x102E: 84,
+ 0x102F: 84,
0x1030: 84,
0x1032: 84,
0x1033: 84,
@@ -1069,13 +1069,13 @@ joining_types = {
0x1036: 84,
0x1037: 84,
0x1039: 84,
- 0x103a: 84,
- 0x103d: 84,
- 0x103e: 84,
+ 0x103A: 84,
+ 0x103D: 84,
+ 0x103E: 84,
0x1058: 84,
0x1059: 84,
- 0x105e: 84,
- 0x105f: 84,
+ 0x105E: 84,
+ 0x105F: 84,
0x1060: 84,
0x1071: 84,
0x1072: 84,
@@ -1084,11 +1084,11 @@ joining_types = {
0x1082: 84,
0x1085: 84,
0x1086: 84,
- 0x108d: 84,
- 0x109d: 84,
- 0x135d: 84,
- 0x135e: 84,
- 0x135f: 84,
+ 0x108D: 84,
+ 0x109D: 84,
+ 0x135D: 84,
+ 0x135E: 84,
+ 0x135F: 84,
0x1712: 84,
0x1713: 84,
0x1714: 84,
@@ -1098,34 +1098,34 @@ joining_types = {
0x1753: 84,
0x1772: 84,
0x1773: 84,
- 0x17b4: 84,
- 0x17b5: 84,
- 0x17b7: 84,
- 0x17b8: 84,
- 0x17b9: 84,
- 0x17ba: 84,
- 0x17bb: 84,
- 0x17bc: 84,
- 0x17bd: 84,
- 0x17c6: 84,
- 0x17c9: 84,
- 0x17ca: 84,
- 0x17cb: 84,
- 0x17cc: 84,
- 0x17cd: 84,
- 0x17ce: 84,
- 0x17cf: 84,
- 0x17d0: 84,
- 0x17d1: 84,
- 0x17d2: 84,
- 0x17d3: 84,
- 0x17dd: 84,
+ 0x17B4: 84,
+ 0x17B5: 84,
+ 0x17B7: 84,
+ 0x17B8: 84,
+ 0x17B9: 84,
+ 0x17BA: 84,
+ 0x17BB: 84,
+ 0x17BC: 84,
+ 0x17BD: 84,
+ 0x17C6: 84,
+ 0x17C9: 84,
+ 0x17CA: 84,
+ 0x17CB: 84,
+ 0x17CC: 84,
+ 0x17CD: 84,
+ 0x17CE: 84,
+ 0x17CF: 84,
+ 0x17D0: 84,
+ 0x17D1: 84,
+ 0x17D2: 84,
+ 0x17D3: 84,
+ 0x17DD: 84,
0x1807: 68,
- 0x180a: 67,
- 0x180b: 84,
- 0x180c: 84,
- 0x180d: 84,
- 0x180f: 84,
+ 0x180A: 67,
+ 0x180B: 84,
+ 0x180C: 84,
+ 0x180D: 84,
+ 0x180F: 84,
0x1820: 68,
0x1821: 68,
0x1822: 68,
@@ -1136,12 +1136,12 @@ joining_types = {
0x1827: 68,
0x1828: 68,
0x1829: 68,
- 0x182a: 68,
- 0x182b: 68,
- 0x182c: 68,
- 0x182d: 68,
- 0x182e: 68,
- 0x182f: 68,
+ 0x182A: 68,
+ 0x182B: 68,
+ 0x182C: 68,
+ 0x182D: 68,
+ 0x182E: 68,
+ 0x182F: 68,
0x1830: 68,
0x1831: 68,
0x1832: 68,
@@ -1152,12 +1152,12 @@ joining_types = {
0x1837: 68,
0x1838: 68,
0x1839: 68,
- 0x183a: 68,
- 0x183b: 68,
- 0x183c: 68,
- 0x183d: 68,
- 0x183e: 68,
- 0x183f: 68,
+ 0x183A: 68,
+ 0x183B: 68,
+ 0x183C: 68,
+ 0x183D: 68,
+ 0x183E: 68,
+ 0x183F: 68,
0x1840: 68,
0x1841: 68,
0x1842: 68,
@@ -1168,12 +1168,12 @@ joining_types = {
0x1847: 68,
0x1848: 68,
0x1849: 68,
- 0x184a: 68,
- 0x184b: 68,
- 0x184c: 68,
- 0x184d: 68,
- 0x184e: 68,
- 0x184f: 68,
+ 0x184A: 68,
+ 0x184B: 68,
+ 0x184C: 68,
+ 0x184D: 68,
+ 0x184E: 68,
+ 0x184F: 68,
0x1850: 68,
0x1851: 68,
0x1852: 68,
@@ -1184,12 +1184,12 @@ joining_types = {
0x1857: 68,
0x1858: 68,
0x1859: 68,
- 0x185a: 68,
- 0x185b: 68,
- 0x185c: 68,
- 0x185d: 68,
- 0x185e: 68,
- 0x185f: 68,
+ 0x185A: 68,
+ 0x185B: 68,
+ 0x185C: 68,
+ 0x185D: 68,
+ 0x185E: 68,
+ 0x185F: 68,
0x1860: 68,
0x1861: 68,
0x1862: 68,
@@ -1200,12 +1200,12 @@ joining_types = {
0x1867: 68,
0x1868: 68,
0x1869: 68,
- 0x186a: 68,
- 0x186b: 68,
- 0x186c: 68,
- 0x186d: 68,
- 0x186e: 68,
- 0x186f: 68,
+ 0x186A: 68,
+ 0x186B: 68,
+ 0x186C: 68,
+ 0x186D: 68,
+ 0x186E: 68,
+ 0x186F: 68,
0x1870: 68,
0x1871: 68,
0x1872: 68,
@@ -1220,12 +1220,12 @@ joining_types = {
0x1887: 68,
0x1888: 68,
0x1889: 68,
- 0x188a: 68,
- 0x188b: 68,
- 0x188c: 68,
- 0x188d: 68,
- 0x188e: 68,
- 0x188f: 68,
+ 0x188A: 68,
+ 0x188B: 68,
+ 0x188C: 68,
+ 0x188D: 68,
+ 0x188E: 68,
+ 0x188F: 68,
0x1890: 68,
0x1891: 68,
0x1892: 68,
@@ -1236,23 +1236,23 @@ joining_types = {
0x1897: 68,
0x1898: 68,
0x1899: 68,
- 0x189a: 68,
- 0x189b: 68,
- 0x189c: 68,
- 0x189d: 68,
- 0x189e: 68,
- 0x189f: 68,
- 0x18a0: 68,
- 0x18a1: 68,
- 0x18a2: 68,
- 0x18a3: 68,
- 0x18a4: 68,
- 0x18a5: 68,
- 0x18a6: 68,
- 0x18a7: 68,
- 0x18a8: 68,
- 0x18a9: 84,
- 0x18aa: 68,
+ 0x189A: 68,
+ 0x189B: 68,
+ 0x189C: 68,
+ 0x189D: 68,
+ 0x189E: 68,
+ 0x189F: 68,
+ 0x18A0: 68,
+ 0x18A1: 68,
+ 0x18A2: 68,
+ 0x18A3: 68,
+ 0x18A4: 68,
+ 0x18A5: 68,
+ 0x18A6: 68,
+ 0x18A7: 68,
+ 0x18A8: 68,
+ 0x18A9: 84,
+ 0x18AA: 68,
0x1920: 84,
0x1921: 84,
0x1922: 84,
@@ -1260,712 +1260,712 @@ joining_types = {
0x1928: 84,
0x1932: 84,
0x1939: 84,
- 0x193a: 84,
- 0x193b: 84,
- 0x1a17: 84,
- 0x1a18: 84,
- 0x1a1b: 84,
- 0x1a56: 84,
- 0x1a58: 84,
- 0x1a59: 84,
- 0x1a5a: 84,
- 0x1a5b: 84,
- 0x1a5c: 84,
- 0x1a5d: 84,
- 0x1a5e: 84,
- 0x1a60: 84,
- 0x1a62: 84,
- 0x1a65: 84,
- 0x1a66: 84,
- 0x1a67: 84,
- 0x1a68: 84,
- 0x1a69: 84,
- 0x1a6a: 84,
- 0x1a6b: 84,
- 0x1a6c: 84,
- 0x1a73: 84,
- 0x1a74: 84,
- 0x1a75: 84,
- 0x1a76: 84,
- 0x1a77: 84,
- 0x1a78: 84,
- 0x1a79: 84,
- 0x1a7a: 84,
- 0x1a7b: 84,
- 0x1a7c: 84,
- 0x1a7f: 84,
- 0x1ab0: 84,
- 0x1ab1: 84,
- 0x1ab2: 84,
- 0x1ab3: 84,
- 0x1ab4: 84,
- 0x1ab5: 84,
- 0x1ab6: 84,
- 0x1ab7: 84,
- 0x1ab8: 84,
- 0x1ab9: 84,
- 0x1aba: 84,
- 0x1abb: 84,
- 0x1abc: 84,
- 0x1abd: 84,
- 0x1abe: 84,
- 0x1abf: 84,
- 0x1ac0: 84,
- 0x1ac1: 84,
- 0x1ac2: 84,
- 0x1ac3: 84,
- 0x1ac4: 84,
- 0x1ac5: 84,
- 0x1ac6: 84,
- 0x1ac7: 84,
- 0x1ac8: 84,
- 0x1ac9: 84,
- 0x1aca: 84,
- 0x1acb: 84,
- 0x1acc: 84,
- 0x1acd: 84,
- 0x1ace: 84,
- 0x1b00: 84,
- 0x1b01: 84,
- 0x1b02: 84,
- 0x1b03: 84,
- 0x1b34: 84,
- 0x1b36: 84,
- 0x1b37: 84,
- 0x1b38: 84,
- 0x1b39: 84,
- 0x1b3a: 84,
- 0x1b3c: 84,
- 0x1b42: 84,
- 0x1b6b: 84,
- 0x1b6c: 84,
- 0x1b6d: 84,
- 0x1b6e: 84,
- 0x1b6f: 84,
- 0x1b70: 84,
- 0x1b71: 84,
- 0x1b72: 84,
- 0x1b73: 84,
- 0x1b80: 84,
- 0x1b81: 84,
- 0x1ba2: 84,
- 0x1ba3: 84,
- 0x1ba4: 84,
- 0x1ba5: 84,
- 0x1ba8: 84,
- 0x1ba9: 84,
- 0x1bab: 84,
- 0x1bac: 84,
- 0x1bad: 84,
- 0x1be6: 84,
- 0x1be8: 84,
- 0x1be9: 84,
- 0x1bed: 84,
- 0x1bef: 84,
- 0x1bf0: 84,
- 0x1bf1: 84,
- 0x1c2c: 84,
- 0x1c2d: 84,
- 0x1c2e: 84,
- 0x1c2f: 84,
- 0x1c30: 84,
- 0x1c31: 84,
- 0x1c32: 84,
- 0x1c33: 84,
- 0x1c36: 84,
- 0x1c37: 84,
- 0x1cd0: 84,
- 0x1cd1: 84,
- 0x1cd2: 84,
- 0x1cd4: 84,
- 0x1cd5: 84,
- 0x1cd6: 84,
- 0x1cd7: 84,
- 0x1cd8: 84,
- 0x1cd9: 84,
- 0x1cda: 84,
- 0x1cdb: 84,
- 0x1cdc: 84,
- 0x1cdd: 84,
- 0x1cde: 84,
- 0x1cdf: 84,
- 0x1ce0: 84,
- 0x1ce2: 84,
- 0x1ce3: 84,
- 0x1ce4: 84,
- 0x1ce5: 84,
- 0x1ce6: 84,
- 0x1ce7: 84,
- 0x1ce8: 84,
- 0x1ced: 84,
- 0x1cf4: 84,
- 0x1cf8: 84,
- 0x1cf9: 84,
- 0x1dc0: 84,
- 0x1dc1: 84,
- 0x1dc2: 84,
- 0x1dc3: 84,
- 0x1dc4: 84,
- 0x1dc5: 84,
- 0x1dc6: 84,
- 0x1dc7: 84,
- 0x1dc8: 84,
- 0x1dc9: 84,
- 0x1dca: 84,
- 0x1dcb: 84,
- 0x1dcc: 84,
- 0x1dcd: 84,
- 0x1dce: 84,
- 0x1dcf: 84,
- 0x1dd0: 84,
- 0x1dd1: 84,
- 0x1dd2: 84,
- 0x1dd3: 84,
- 0x1dd4: 84,
- 0x1dd5: 84,
- 0x1dd6: 84,
- 0x1dd7: 84,
- 0x1dd8: 84,
- 0x1dd9: 84,
- 0x1dda: 84,
- 0x1ddb: 84,
- 0x1ddc: 84,
- 0x1ddd: 84,
- 0x1dde: 84,
- 0x1ddf: 84,
- 0x1de0: 84,
- 0x1de1: 84,
- 0x1de2: 84,
- 0x1de3: 84,
- 0x1de4: 84,
- 0x1de5: 84,
- 0x1de6: 84,
- 0x1de7: 84,
- 0x1de8: 84,
- 0x1de9: 84,
- 0x1dea: 84,
- 0x1deb: 84,
- 0x1dec: 84,
- 0x1ded: 84,
- 0x1dee: 84,
- 0x1def: 84,
- 0x1df0: 84,
- 0x1df1: 84,
- 0x1df2: 84,
- 0x1df3: 84,
- 0x1df4: 84,
- 0x1df5: 84,
- 0x1df6: 84,
- 0x1df7: 84,
- 0x1df8: 84,
- 0x1df9: 84,
- 0x1dfa: 84,
- 0x1dfb: 84,
- 0x1dfc: 84,
- 0x1dfd: 84,
- 0x1dfe: 84,
- 0x1dff: 84,
- 0x200b: 84,
- 0x200d: 67,
- 0x200e: 84,
- 0x200f: 84,
- 0x202a: 84,
- 0x202b: 84,
- 0x202c: 84,
- 0x202d: 84,
- 0x202e: 84,
+ 0x193A: 84,
+ 0x193B: 84,
+ 0x1A17: 84,
+ 0x1A18: 84,
+ 0x1A1B: 84,
+ 0x1A56: 84,
+ 0x1A58: 84,
+ 0x1A59: 84,
+ 0x1A5A: 84,
+ 0x1A5B: 84,
+ 0x1A5C: 84,
+ 0x1A5D: 84,
+ 0x1A5E: 84,
+ 0x1A60: 84,
+ 0x1A62: 84,
+ 0x1A65: 84,
+ 0x1A66: 84,
+ 0x1A67: 84,
+ 0x1A68: 84,
+ 0x1A69: 84,
+ 0x1A6A: 84,
+ 0x1A6B: 84,
+ 0x1A6C: 84,
+ 0x1A73: 84,
+ 0x1A74: 84,
+ 0x1A75: 84,
+ 0x1A76: 84,
+ 0x1A77: 84,
+ 0x1A78: 84,
+ 0x1A79: 84,
+ 0x1A7A: 84,
+ 0x1A7B: 84,
+ 0x1A7C: 84,
+ 0x1A7F: 84,
+ 0x1AB0: 84,
+ 0x1AB1: 84,
+ 0x1AB2: 84,
+ 0x1AB3: 84,
+ 0x1AB4: 84,
+ 0x1AB5: 84,
+ 0x1AB6: 84,
+ 0x1AB7: 84,
+ 0x1AB8: 84,
+ 0x1AB9: 84,
+ 0x1ABA: 84,
+ 0x1ABB: 84,
+ 0x1ABC: 84,
+ 0x1ABD: 84,
+ 0x1ABE: 84,
+ 0x1ABF: 84,
+ 0x1AC0: 84,
+ 0x1AC1: 84,
+ 0x1AC2: 84,
+ 0x1AC3: 84,
+ 0x1AC4: 84,
+ 0x1AC5: 84,
+ 0x1AC6: 84,
+ 0x1AC7: 84,
+ 0x1AC8: 84,
+ 0x1AC9: 84,
+ 0x1ACA: 84,
+ 0x1ACB: 84,
+ 0x1ACC: 84,
+ 0x1ACD: 84,
+ 0x1ACE: 84,
+ 0x1B00: 84,
+ 0x1B01: 84,
+ 0x1B02: 84,
+ 0x1B03: 84,
+ 0x1B34: 84,
+ 0x1B36: 84,
+ 0x1B37: 84,
+ 0x1B38: 84,
+ 0x1B39: 84,
+ 0x1B3A: 84,
+ 0x1B3C: 84,
+ 0x1B42: 84,
+ 0x1B6B: 84,
+ 0x1B6C: 84,
+ 0x1B6D: 84,
+ 0x1B6E: 84,
+ 0x1B6F: 84,
+ 0x1B70: 84,
+ 0x1B71: 84,
+ 0x1B72: 84,
+ 0x1B73: 84,
+ 0x1B80: 84,
+ 0x1B81: 84,
+ 0x1BA2: 84,
+ 0x1BA3: 84,
+ 0x1BA4: 84,
+ 0x1BA5: 84,
+ 0x1BA8: 84,
+ 0x1BA9: 84,
+ 0x1BAB: 84,
+ 0x1BAC: 84,
+ 0x1BAD: 84,
+ 0x1BE6: 84,
+ 0x1BE8: 84,
+ 0x1BE9: 84,
+ 0x1BED: 84,
+ 0x1BEF: 84,
+ 0x1BF0: 84,
+ 0x1BF1: 84,
+ 0x1C2C: 84,
+ 0x1C2D: 84,
+ 0x1C2E: 84,
+ 0x1C2F: 84,
+ 0x1C30: 84,
+ 0x1C31: 84,
+ 0x1C32: 84,
+ 0x1C33: 84,
+ 0x1C36: 84,
+ 0x1C37: 84,
+ 0x1CD0: 84,
+ 0x1CD1: 84,
+ 0x1CD2: 84,
+ 0x1CD4: 84,
+ 0x1CD5: 84,
+ 0x1CD6: 84,
+ 0x1CD7: 84,
+ 0x1CD8: 84,
+ 0x1CD9: 84,
+ 0x1CDA: 84,
+ 0x1CDB: 84,
+ 0x1CDC: 84,
+ 0x1CDD: 84,
+ 0x1CDE: 84,
+ 0x1CDF: 84,
+ 0x1CE0: 84,
+ 0x1CE2: 84,
+ 0x1CE3: 84,
+ 0x1CE4: 84,
+ 0x1CE5: 84,
+ 0x1CE6: 84,
+ 0x1CE7: 84,
+ 0x1CE8: 84,
+ 0x1CED: 84,
+ 0x1CF4: 84,
+ 0x1CF8: 84,
+ 0x1CF9: 84,
+ 0x1DC0: 84,
+ 0x1DC1: 84,
+ 0x1DC2: 84,
+ 0x1DC3: 84,
+ 0x1DC4: 84,
+ 0x1DC5: 84,
+ 0x1DC6: 84,
+ 0x1DC7: 84,
+ 0x1DC8: 84,
+ 0x1DC9: 84,
+ 0x1DCA: 84,
+ 0x1DCB: 84,
+ 0x1DCC: 84,
+ 0x1DCD: 84,
+ 0x1DCE: 84,
+ 0x1DCF: 84,
+ 0x1DD0: 84,
+ 0x1DD1: 84,
+ 0x1DD2: 84,
+ 0x1DD3: 84,
+ 0x1DD4: 84,
+ 0x1DD5: 84,
+ 0x1DD6: 84,
+ 0x1DD7: 84,
+ 0x1DD8: 84,
+ 0x1DD9: 84,
+ 0x1DDA: 84,
+ 0x1DDB: 84,
+ 0x1DDC: 84,
+ 0x1DDD: 84,
+ 0x1DDE: 84,
+ 0x1DDF: 84,
+ 0x1DE0: 84,
+ 0x1DE1: 84,
+ 0x1DE2: 84,
+ 0x1DE3: 84,
+ 0x1DE4: 84,
+ 0x1DE5: 84,
+ 0x1DE6: 84,
+ 0x1DE7: 84,
+ 0x1DE8: 84,
+ 0x1DE9: 84,
+ 0x1DEA: 84,
+ 0x1DEB: 84,
+ 0x1DEC: 84,
+ 0x1DED: 84,
+ 0x1DEE: 84,
+ 0x1DEF: 84,
+ 0x1DF0: 84,
+ 0x1DF1: 84,
+ 0x1DF2: 84,
+ 0x1DF3: 84,
+ 0x1DF4: 84,
+ 0x1DF5: 84,
+ 0x1DF6: 84,
+ 0x1DF7: 84,
+ 0x1DF8: 84,
+ 0x1DF9: 84,
+ 0x1DFA: 84,
+ 0x1DFB: 84,
+ 0x1DFC: 84,
+ 0x1DFD: 84,
+ 0x1DFE: 84,
+ 0x1DFF: 84,
+ 0x200B: 84,
+ 0x200D: 67,
+ 0x200E: 84,
+ 0x200F: 84,
+ 0x202A: 84,
+ 0x202B: 84,
+ 0x202C: 84,
+ 0x202D: 84,
+ 0x202E: 84,
0x2060: 84,
0x2061: 84,
0x2062: 84,
0x2063: 84,
0x2064: 84,
- 0x206a: 84,
- 0x206b: 84,
- 0x206c: 84,
- 0x206d: 84,
- 0x206e: 84,
- 0x206f: 84,
- 0x20d0: 84,
- 0x20d1: 84,
- 0x20d2: 84,
- 0x20d3: 84,
- 0x20d4: 84,
- 0x20d5: 84,
- 0x20d6: 84,
- 0x20d7: 84,
- 0x20d8: 84,
- 0x20d9: 84,
- 0x20da: 84,
- 0x20db: 84,
- 0x20dc: 84,
- 0x20dd: 84,
- 0x20de: 84,
- 0x20df: 84,
- 0x20e0: 84,
- 0x20e1: 84,
- 0x20e2: 84,
- 0x20e3: 84,
- 0x20e4: 84,
- 0x20e5: 84,
- 0x20e6: 84,
- 0x20e7: 84,
- 0x20e8: 84,
- 0x20e9: 84,
- 0x20ea: 84,
- 0x20eb: 84,
- 0x20ec: 84,
- 0x20ed: 84,
- 0x20ee: 84,
- 0x20ef: 84,
- 0x20f0: 84,
- 0x2cef: 84,
- 0x2cf0: 84,
- 0x2cf1: 84,
- 0x2d7f: 84,
- 0x2de0: 84,
- 0x2de1: 84,
- 0x2de2: 84,
- 0x2de3: 84,
- 0x2de4: 84,
- 0x2de5: 84,
- 0x2de6: 84,
- 0x2de7: 84,
- 0x2de8: 84,
- 0x2de9: 84,
- 0x2dea: 84,
- 0x2deb: 84,
- 0x2dec: 84,
- 0x2ded: 84,
- 0x2dee: 84,
- 0x2def: 84,
- 0x2df0: 84,
- 0x2df1: 84,
- 0x2df2: 84,
- 0x2df3: 84,
- 0x2df4: 84,
- 0x2df5: 84,
- 0x2df6: 84,
- 0x2df7: 84,
- 0x2df8: 84,
- 0x2df9: 84,
- 0x2dfa: 84,
- 0x2dfb: 84,
- 0x2dfc: 84,
- 0x2dfd: 84,
- 0x2dfe: 84,
- 0x2dff: 84,
- 0x302a: 84,
- 0x302b: 84,
- 0x302c: 84,
- 0x302d: 84,
+ 0x206A: 84,
+ 0x206B: 84,
+ 0x206C: 84,
+ 0x206D: 84,
+ 0x206E: 84,
+ 0x206F: 84,
+ 0x20D0: 84,
+ 0x20D1: 84,
+ 0x20D2: 84,
+ 0x20D3: 84,
+ 0x20D4: 84,
+ 0x20D5: 84,
+ 0x20D6: 84,
+ 0x20D7: 84,
+ 0x20D8: 84,
+ 0x20D9: 84,
+ 0x20DA: 84,
+ 0x20DB: 84,
+ 0x20DC: 84,
+ 0x20DD: 84,
+ 0x20DE: 84,
+ 0x20DF: 84,
+ 0x20E0: 84,
+ 0x20E1: 84,
+ 0x20E2: 84,
+ 0x20E3: 84,
+ 0x20E4: 84,
+ 0x20E5: 84,
+ 0x20E6: 84,
+ 0x20E7: 84,
+ 0x20E8: 84,
+ 0x20E9: 84,
+ 0x20EA: 84,
+ 0x20EB: 84,
+ 0x20EC: 84,
+ 0x20ED: 84,
+ 0x20EE: 84,
+ 0x20EF: 84,
+ 0x20F0: 84,
+ 0x2CEF: 84,
+ 0x2CF0: 84,
+ 0x2CF1: 84,
+ 0x2D7F: 84,
+ 0x2DE0: 84,
+ 0x2DE1: 84,
+ 0x2DE2: 84,
+ 0x2DE3: 84,
+ 0x2DE4: 84,
+ 0x2DE5: 84,
+ 0x2DE6: 84,
+ 0x2DE7: 84,
+ 0x2DE8: 84,
+ 0x2DE9: 84,
+ 0x2DEA: 84,
+ 0x2DEB: 84,
+ 0x2DEC: 84,
+ 0x2DED: 84,
+ 0x2DEE: 84,
+ 0x2DEF: 84,
+ 0x2DF0: 84,
+ 0x2DF1: 84,
+ 0x2DF2: 84,
+ 0x2DF3: 84,
+ 0x2DF4: 84,
+ 0x2DF5: 84,
+ 0x2DF6: 84,
+ 0x2DF7: 84,
+ 0x2DF8: 84,
+ 0x2DF9: 84,
+ 0x2DFA: 84,
+ 0x2DFB: 84,
+ 0x2DFC: 84,
+ 0x2DFD: 84,
+ 0x2DFE: 84,
+ 0x2DFF: 84,
+ 0x302A: 84,
+ 0x302B: 84,
+ 0x302C: 84,
+ 0x302D: 84,
0x3099: 84,
- 0x309a: 84,
- 0xa66f: 84,
- 0xa670: 84,
- 0xa671: 84,
- 0xa672: 84,
- 0xa674: 84,
- 0xa675: 84,
- 0xa676: 84,
- 0xa677: 84,
- 0xa678: 84,
- 0xa679: 84,
- 0xa67a: 84,
- 0xa67b: 84,
- 0xa67c: 84,
- 0xa67d: 84,
- 0xa69e: 84,
- 0xa69f: 84,
- 0xa6f0: 84,
- 0xa6f1: 84,
- 0xa802: 84,
- 0xa806: 84,
- 0xa80b: 84,
- 0xa825: 84,
- 0xa826: 84,
- 0xa82c: 84,
- 0xa840: 68,
- 0xa841: 68,
- 0xa842: 68,
- 0xa843: 68,
- 0xa844: 68,
- 0xa845: 68,
- 0xa846: 68,
- 0xa847: 68,
- 0xa848: 68,
- 0xa849: 68,
- 0xa84a: 68,
- 0xa84b: 68,
- 0xa84c: 68,
- 0xa84d: 68,
- 0xa84e: 68,
- 0xa84f: 68,
- 0xa850: 68,
- 0xa851: 68,
- 0xa852: 68,
- 0xa853: 68,
- 0xa854: 68,
- 0xa855: 68,
- 0xa856: 68,
- 0xa857: 68,
- 0xa858: 68,
- 0xa859: 68,
- 0xa85a: 68,
- 0xa85b: 68,
- 0xa85c: 68,
- 0xa85d: 68,
- 0xa85e: 68,
- 0xa85f: 68,
- 0xa860: 68,
- 0xa861: 68,
- 0xa862: 68,
- 0xa863: 68,
- 0xa864: 68,
- 0xa865: 68,
- 0xa866: 68,
- 0xa867: 68,
- 0xa868: 68,
- 0xa869: 68,
- 0xa86a: 68,
- 0xa86b: 68,
- 0xa86c: 68,
- 0xa86d: 68,
- 0xa86e: 68,
- 0xa86f: 68,
- 0xa870: 68,
- 0xa871: 68,
- 0xa872: 76,
- 0xa8c4: 84,
- 0xa8c5: 84,
- 0xa8e0: 84,
- 0xa8e1: 84,
- 0xa8e2: 84,
- 0xa8e3: 84,
- 0xa8e4: 84,
- 0xa8e5: 84,
- 0xa8e6: 84,
- 0xa8e7: 84,
- 0xa8e8: 84,
- 0xa8e9: 84,
- 0xa8ea: 84,
- 0xa8eb: 84,
- 0xa8ec: 84,
- 0xa8ed: 84,
- 0xa8ee: 84,
- 0xa8ef: 84,
- 0xa8f0: 84,
- 0xa8f1: 84,
- 0xa8ff: 84,
- 0xa926: 84,
- 0xa927: 84,
- 0xa928: 84,
- 0xa929: 84,
- 0xa92a: 84,
- 0xa92b: 84,
- 0xa92c: 84,
- 0xa92d: 84,
- 0xa947: 84,
- 0xa948: 84,
- 0xa949: 84,
- 0xa94a: 84,
- 0xa94b: 84,
- 0xa94c: 84,
- 0xa94d: 84,
- 0xa94e: 84,
- 0xa94f: 84,
- 0xa950: 84,
- 0xa951: 84,
- 0xa980: 84,
- 0xa981: 84,
- 0xa982: 84,
- 0xa9b3: 84,
- 0xa9b6: 84,
- 0xa9b7: 84,
- 0xa9b8: 84,
- 0xa9b9: 84,
- 0xa9bc: 84,
- 0xa9bd: 84,
- 0xa9e5: 84,
- 0xaa29: 84,
- 0xaa2a: 84,
- 0xaa2b: 84,
- 0xaa2c: 84,
- 0xaa2d: 84,
- 0xaa2e: 84,
- 0xaa31: 84,
- 0xaa32: 84,
- 0xaa35: 84,
- 0xaa36: 84,
- 0xaa43: 84,
- 0xaa4c: 84,
- 0xaa7c: 84,
- 0xaab0: 84,
- 0xaab2: 84,
- 0xaab3: 84,
- 0xaab4: 84,
- 0xaab7: 84,
- 0xaab8: 84,
- 0xaabe: 84,
- 0xaabf: 84,
- 0xaac1: 84,
- 0xaaec: 84,
- 0xaaed: 84,
- 0xaaf6: 84,
- 0xabe5: 84,
- 0xabe8: 84,
- 0xabed: 84,
- 0xfb1e: 84,
- 0xfe00: 84,
- 0xfe01: 84,
- 0xfe02: 84,
- 0xfe03: 84,
- 0xfe04: 84,
- 0xfe05: 84,
- 0xfe06: 84,
- 0xfe07: 84,
- 0xfe08: 84,
- 0xfe09: 84,
- 0xfe0a: 84,
- 0xfe0b: 84,
- 0xfe0c: 84,
- 0xfe0d: 84,
- 0xfe0e: 84,
- 0xfe0f: 84,
- 0xfe20: 84,
- 0xfe21: 84,
- 0xfe22: 84,
- 0xfe23: 84,
- 0xfe24: 84,
- 0xfe25: 84,
- 0xfe26: 84,
- 0xfe27: 84,
- 0xfe28: 84,
- 0xfe29: 84,
- 0xfe2a: 84,
- 0xfe2b: 84,
- 0xfe2c: 84,
- 0xfe2d: 84,
- 0xfe2e: 84,
- 0xfe2f: 84,
- 0xfeff: 84,
- 0xfff9: 84,
- 0xfffa: 84,
- 0xfffb: 84,
- 0x101fd: 84,
- 0x102e0: 84,
+ 0x309A: 84,
+ 0xA66F: 84,
+ 0xA670: 84,
+ 0xA671: 84,
+ 0xA672: 84,
+ 0xA674: 84,
+ 0xA675: 84,
+ 0xA676: 84,
+ 0xA677: 84,
+ 0xA678: 84,
+ 0xA679: 84,
+ 0xA67A: 84,
+ 0xA67B: 84,
+ 0xA67C: 84,
+ 0xA67D: 84,
+ 0xA69E: 84,
+ 0xA69F: 84,
+ 0xA6F0: 84,
+ 0xA6F1: 84,
+ 0xA802: 84,
+ 0xA806: 84,
+ 0xA80B: 84,
+ 0xA825: 84,
+ 0xA826: 84,
+ 0xA82C: 84,
+ 0xA840: 68,
+ 0xA841: 68,
+ 0xA842: 68,
+ 0xA843: 68,
+ 0xA844: 68,
+ 0xA845: 68,
+ 0xA846: 68,
+ 0xA847: 68,
+ 0xA848: 68,
+ 0xA849: 68,
+ 0xA84A: 68,
+ 0xA84B: 68,
+ 0xA84C: 68,
+ 0xA84D: 68,
+ 0xA84E: 68,
+ 0xA84F: 68,
+ 0xA850: 68,
+ 0xA851: 68,
+ 0xA852: 68,
+ 0xA853: 68,
+ 0xA854: 68,
+ 0xA855: 68,
+ 0xA856: 68,
+ 0xA857: 68,
+ 0xA858: 68,
+ 0xA859: 68,
+ 0xA85A: 68,
+ 0xA85B: 68,
+ 0xA85C: 68,
+ 0xA85D: 68,
+ 0xA85E: 68,
+ 0xA85F: 68,
+ 0xA860: 68,
+ 0xA861: 68,
+ 0xA862: 68,
+ 0xA863: 68,
+ 0xA864: 68,
+ 0xA865: 68,
+ 0xA866: 68,
+ 0xA867: 68,
+ 0xA868: 68,
+ 0xA869: 68,
+ 0xA86A: 68,
+ 0xA86B: 68,
+ 0xA86C: 68,
+ 0xA86D: 68,
+ 0xA86E: 68,
+ 0xA86F: 68,
+ 0xA870: 68,
+ 0xA871: 68,
+ 0xA872: 76,
+ 0xA8C4: 84,
+ 0xA8C5: 84,
+ 0xA8E0: 84,
+ 0xA8E1: 84,
+ 0xA8E2: 84,
+ 0xA8E3: 84,
+ 0xA8E4: 84,
+ 0xA8E5: 84,
+ 0xA8E6: 84,
+ 0xA8E7: 84,
+ 0xA8E8: 84,
+ 0xA8E9: 84,
+ 0xA8EA: 84,
+ 0xA8EB: 84,
+ 0xA8EC: 84,
+ 0xA8ED: 84,
+ 0xA8EE: 84,
+ 0xA8EF: 84,
+ 0xA8F0: 84,
+ 0xA8F1: 84,
+ 0xA8FF: 84,
+ 0xA926: 84,
+ 0xA927: 84,
+ 0xA928: 84,
+ 0xA929: 84,
+ 0xA92A: 84,
+ 0xA92B: 84,
+ 0xA92C: 84,
+ 0xA92D: 84,
+ 0xA947: 84,
+ 0xA948: 84,
+ 0xA949: 84,
+ 0xA94A: 84,
+ 0xA94B: 84,
+ 0xA94C: 84,
+ 0xA94D: 84,
+ 0xA94E: 84,
+ 0xA94F: 84,
+ 0xA950: 84,
+ 0xA951: 84,
+ 0xA980: 84,
+ 0xA981: 84,
+ 0xA982: 84,
+ 0xA9B3: 84,
+ 0xA9B6: 84,
+ 0xA9B7: 84,
+ 0xA9B8: 84,
+ 0xA9B9: 84,
+ 0xA9BC: 84,
+ 0xA9BD: 84,
+ 0xA9E5: 84,
+ 0xAA29: 84,
+ 0xAA2A: 84,
+ 0xAA2B: 84,
+ 0xAA2C: 84,
+ 0xAA2D: 84,
+ 0xAA2E: 84,
+ 0xAA31: 84,
+ 0xAA32: 84,
+ 0xAA35: 84,
+ 0xAA36: 84,
+ 0xAA43: 84,
+ 0xAA4C: 84,
+ 0xAA7C: 84,
+ 0xAAB0: 84,
+ 0xAAB2: 84,
+ 0xAAB3: 84,
+ 0xAAB4: 84,
+ 0xAAB7: 84,
+ 0xAAB8: 84,
+ 0xAABE: 84,
+ 0xAABF: 84,
+ 0xAAC1: 84,
+ 0xAAEC: 84,
+ 0xAAED: 84,
+ 0xAAF6: 84,
+ 0xABE5: 84,
+ 0xABE8: 84,
+ 0xABED: 84,
+ 0xFB1E: 84,
+ 0xFE00: 84,
+ 0xFE01: 84,
+ 0xFE02: 84,
+ 0xFE03: 84,
+ 0xFE04: 84,
+ 0xFE05: 84,
+ 0xFE06: 84,
+ 0xFE07: 84,
+ 0xFE08: 84,
+ 0xFE09: 84,
+ 0xFE0A: 84,
+ 0xFE0B: 84,
+ 0xFE0C: 84,
+ 0xFE0D: 84,
+ 0xFE0E: 84,
+ 0xFE0F: 84,
+ 0xFE20: 84,
+ 0xFE21: 84,
+ 0xFE22: 84,
+ 0xFE23: 84,
+ 0xFE24: 84,
+ 0xFE25: 84,
+ 0xFE26: 84,
+ 0xFE27: 84,
+ 0xFE28: 84,
+ 0xFE29: 84,
+ 0xFE2A: 84,
+ 0xFE2B: 84,
+ 0xFE2C: 84,
+ 0xFE2D: 84,
+ 0xFE2E: 84,
+ 0xFE2F: 84,
+ 0xFEFF: 84,
+ 0xFFF9: 84,
+ 0xFFFA: 84,
+ 0xFFFB: 84,
+ 0x101FD: 84,
+ 0x102E0: 84,
0x10376: 84,
0x10377: 84,
0x10378: 84,
0x10379: 84,
- 0x1037a: 84,
- 0x10a01: 84,
- 0x10a02: 84,
- 0x10a03: 84,
- 0x10a05: 84,
- 0x10a06: 84,
- 0x10a0c: 84,
- 0x10a0d: 84,
- 0x10a0e: 84,
- 0x10a0f: 84,
- 0x10a38: 84,
- 0x10a39: 84,
- 0x10a3a: 84,
- 0x10a3f: 84,
- 0x10ac0: 68,
- 0x10ac1: 68,
- 0x10ac2: 68,
- 0x10ac3: 68,
- 0x10ac4: 68,
- 0x10ac5: 82,
- 0x10ac7: 82,
- 0x10ac9: 82,
- 0x10aca: 82,
- 0x10acd: 76,
- 0x10ace: 82,
- 0x10acf: 82,
- 0x10ad0: 82,
- 0x10ad1: 82,
- 0x10ad2: 82,
- 0x10ad3: 68,
- 0x10ad4: 68,
- 0x10ad5: 68,
- 0x10ad6: 68,
- 0x10ad7: 76,
- 0x10ad8: 68,
- 0x10ad9: 68,
- 0x10ada: 68,
- 0x10adb: 68,
- 0x10adc: 68,
- 0x10add: 82,
- 0x10ade: 68,
- 0x10adf: 68,
- 0x10ae0: 68,
- 0x10ae1: 82,
- 0x10ae4: 82,
- 0x10ae5: 84,
- 0x10ae6: 84,
- 0x10aeb: 68,
- 0x10aec: 68,
- 0x10aed: 68,
- 0x10aee: 68,
- 0x10aef: 82,
- 0x10b80: 68,
- 0x10b81: 82,
- 0x10b82: 68,
- 0x10b83: 82,
- 0x10b84: 82,
- 0x10b85: 82,
- 0x10b86: 68,
- 0x10b87: 68,
- 0x10b88: 68,
- 0x10b89: 82,
- 0x10b8a: 68,
- 0x10b8b: 68,
- 0x10b8c: 82,
- 0x10b8d: 68,
- 0x10b8e: 82,
- 0x10b8f: 82,
- 0x10b90: 68,
- 0x10b91: 82,
- 0x10ba9: 82,
- 0x10baa: 82,
- 0x10bab: 82,
- 0x10bac: 82,
- 0x10bad: 68,
- 0x10bae: 68,
- 0x10d00: 76,
- 0x10d01: 68,
- 0x10d02: 68,
- 0x10d03: 68,
- 0x10d04: 68,
- 0x10d05: 68,
- 0x10d06: 68,
- 0x10d07: 68,
- 0x10d08: 68,
- 0x10d09: 68,
- 0x10d0a: 68,
- 0x10d0b: 68,
- 0x10d0c: 68,
- 0x10d0d: 68,
- 0x10d0e: 68,
- 0x10d0f: 68,
- 0x10d10: 68,
- 0x10d11: 68,
- 0x10d12: 68,
- 0x10d13: 68,
- 0x10d14: 68,
- 0x10d15: 68,
- 0x10d16: 68,
- 0x10d17: 68,
- 0x10d18: 68,
- 0x10d19: 68,
- 0x10d1a: 68,
- 0x10d1b: 68,
- 0x10d1c: 68,
- 0x10d1d: 68,
- 0x10d1e: 68,
- 0x10d1f: 68,
- 0x10d20: 68,
- 0x10d21: 68,
- 0x10d22: 82,
- 0x10d23: 68,
- 0x10d24: 84,
- 0x10d25: 84,
- 0x10d26: 84,
- 0x10d27: 84,
- 0x10eab: 84,
- 0x10eac: 84,
- 0x10efd: 84,
- 0x10efe: 84,
- 0x10eff: 84,
- 0x10f30: 68,
- 0x10f31: 68,
- 0x10f32: 68,
- 0x10f33: 82,
- 0x10f34: 68,
- 0x10f35: 68,
- 0x10f36: 68,
- 0x10f37: 68,
- 0x10f38: 68,
- 0x10f39: 68,
- 0x10f3a: 68,
- 0x10f3b: 68,
- 0x10f3c: 68,
- 0x10f3d: 68,
- 0x10f3e: 68,
- 0x10f3f: 68,
- 0x10f40: 68,
- 0x10f41: 68,
- 0x10f42: 68,
- 0x10f43: 68,
- 0x10f44: 68,
- 0x10f46: 84,
- 0x10f47: 84,
- 0x10f48: 84,
- 0x10f49: 84,
- 0x10f4a: 84,
- 0x10f4b: 84,
- 0x10f4c: 84,
- 0x10f4d: 84,
- 0x10f4e: 84,
- 0x10f4f: 84,
- 0x10f50: 84,
- 0x10f51: 68,
- 0x10f52: 68,
- 0x10f53: 68,
- 0x10f54: 82,
- 0x10f70: 68,
- 0x10f71: 68,
- 0x10f72: 68,
- 0x10f73: 68,
- 0x10f74: 82,
- 0x10f75: 82,
- 0x10f76: 68,
- 0x10f77: 68,
- 0x10f78: 68,
- 0x10f79: 68,
- 0x10f7a: 68,
- 0x10f7b: 68,
- 0x10f7c: 68,
- 0x10f7d: 68,
- 0x10f7e: 68,
- 0x10f7f: 68,
- 0x10f80: 68,
- 0x10f81: 68,
- 0x10f82: 84,
- 0x10f83: 84,
- 0x10f84: 84,
- 0x10f85: 84,
- 0x10fb0: 68,
- 0x10fb2: 68,
- 0x10fb3: 68,
- 0x10fb4: 82,
- 0x10fb5: 82,
- 0x10fb6: 82,
- 0x10fb8: 68,
- 0x10fb9: 82,
- 0x10fba: 82,
- 0x10fbb: 68,
- 0x10fbc: 68,
- 0x10fbd: 82,
- 0x10fbe: 68,
- 0x10fbf: 68,
- 0x10fc1: 68,
- 0x10fc2: 82,
- 0x10fc3: 82,
- 0x10fc4: 68,
- 0x10fc9: 82,
- 0x10fca: 68,
- 0x10fcb: 76,
+ 0x1037A: 84,
+ 0x10A01: 84,
+ 0x10A02: 84,
+ 0x10A03: 84,
+ 0x10A05: 84,
+ 0x10A06: 84,
+ 0x10A0C: 84,
+ 0x10A0D: 84,
+ 0x10A0E: 84,
+ 0x10A0F: 84,
+ 0x10A38: 84,
+ 0x10A39: 84,
+ 0x10A3A: 84,
+ 0x10A3F: 84,
+ 0x10AC0: 68,
+ 0x10AC1: 68,
+ 0x10AC2: 68,
+ 0x10AC3: 68,
+ 0x10AC4: 68,
+ 0x10AC5: 82,
+ 0x10AC7: 82,
+ 0x10AC9: 82,
+ 0x10ACA: 82,
+ 0x10ACD: 76,
+ 0x10ACE: 82,
+ 0x10ACF: 82,
+ 0x10AD0: 82,
+ 0x10AD1: 82,
+ 0x10AD2: 82,
+ 0x10AD3: 68,
+ 0x10AD4: 68,
+ 0x10AD5: 68,
+ 0x10AD6: 68,
+ 0x10AD7: 76,
+ 0x10AD8: 68,
+ 0x10AD9: 68,
+ 0x10ADA: 68,
+ 0x10ADB: 68,
+ 0x10ADC: 68,
+ 0x10ADD: 82,
+ 0x10ADE: 68,
+ 0x10ADF: 68,
+ 0x10AE0: 68,
+ 0x10AE1: 82,
+ 0x10AE4: 82,
+ 0x10AE5: 84,
+ 0x10AE6: 84,
+ 0x10AEB: 68,
+ 0x10AEC: 68,
+ 0x10AED: 68,
+ 0x10AEE: 68,
+ 0x10AEF: 82,
+ 0x10B80: 68,
+ 0x10B81: 82,
+ 0x10B82: 68,
+ 0x10B83: 82,
+ 0x10B84: 82,
+ 0x10B85: 82,
+ 0x10B86: 68,
+ 0x10B87: 68,
+ 0x10B88: 68,
+ 0x10B89: 82,
+ 0x10B8A: 68,
+ 0x10B8B: 68,
+ 0x10B8C: 82,
+ 0x10B8D: 68,
+ 0x10B8E: 82,
+ 0x10B8F: 82,
+ 0x10B90: 68,
+ 0x10B91: 82,
+ 0x10BA9: 82,
+ 0x10BAA: 82,
+ 0x10BAB: 82,
+ 0x10BAC: 82,
+ 0x10BAD: 68,
+ 0x10BAE: 68,
+ 0x10D00: 76,
+ 0x10D01: 68,
+ 0x10D02: 68,
+ 0x10D03: 68,
+ 0x10D04: 68,
+ 0x10D05: 68,
+ 0x10D06: 68,
+ 0x10D07: 68,
+ 0x10D08: 68,
+ 0x10D09: 68,
+ 0x10D0A: 68,
+ 0x10D0B: 68,
+ 0x10D0C: 68,
+ 0x10D0D: 68,
+ 0x10D0E: 68,
+ 0x10D0F: 68,
+ 0x10D10: 68,
+ 0x10D11: 68,
+ 0x10D12: 68,
+ 0x10D13: 68,
+ 0x10D14: 68,
+ 0x10D15: 68,
+ 0x10D16: 68,
+ 0x10D17: 68,
+ 0x10D18: 68,
+ 0x10D19: 68,
+ 0x10D1A: 68,
+ 0x10D1B: 68,
+ 0x10D1C: 68,
+ 0x10D1D: 68,
+ 0x10D1E: 68,
+ 0x10D1F: 68,
+ 0x10D20: 68,
+ 0x10D21: 68,
+ 0x10D22: 82,
+ 0x10D23: 68,
+ 0x10D24: 84,
+ 0x10D25: 84,
+ 0x10D26: 84,
+ 0x10D27: 84,
+ 0x10EAB: 84,
+ 0x10EAC: 84,
+ 0x10EFD: 84,
+ 0x10EFE: 84,
+ 0x10EFF: 84,
+ 0x10F30: 68,
+ 0x10F31: 68,
+ 0x10F32: 68,
+ 0x10F33: 82,
+ 0x10F34: 68,
+ 0x10F35: 68,
+ 0x10F36: 68,
+ 0x10F37: 68,
+ 0x10F38: 68,
+ 0x10F39: 68,
+ 0x10F3A: 68,
+ 0x10F3B: 68,
+ 0x10F3C: 68,
+ 0x10F3D: 68,
+ 0x10F3E: 68,
+ 0x10F3F: 68,
+ 0x10F40: 68,
+ 0x10F41: 68,
+ 0x10F42: 68,
+ 0x10F43: 68,
+ 0x10F44: 68,
+ 0x10F46: 84,
+ 0x10F47: 84,
+ 0x10F48: 84,
+ 0x10F49: 84,
+ 0x10F4A: 84,
+ 0x10F4B: 84,
+ 0x10F4C: 84,
+ 0x10F4D: 84,
+ 0x10F4E: 84,
+ 0x10F4F: 84,
+ 0x10F50: 84,
+ 0x10F51: 68,
+ 0x10F52: 68,
+ 0x10F53: 68,
+ 0x10F54: 82,
+ 0x10F70: 68,
+ 0x10F71: 68,
+ 0x10F72: 68,
+ 0x10F73: 68,
+ 0x10F74: 82,
+ 0x10F75: 82,
+ 0x10F76: 68,
+ 0x10F77: 68,
+ 0x10F78: 68,
+ 0x10F79: 68,
+ 0x10F7A: 68,
+ 0x10F7B: 68,
+ 0x10F7C: 68,
+ 0x10F7D: 68,
+ 0x10F7E: 68,
+ 0x10F7F: 68,
+ 0x10F80: 68,
+ 0x10F81: 68,
+ 0x10F82: 84,
+ 0x10F83: 84,
+ 0x10F84: 84,
+ 0x10F85: 84,
+ 0x10FB0: 68,
+ 0x10FB2: 68,
+ 0x10FB3: 68,
+ 0x10FB4: 82,
+ 0x10FB5: 82,
+ 0x10FB6: 82,
+ 0x10FB8: 68,
+ 0x10FB9: 82,
+ 0x10FBA: 82,
+ 0x10FBB: 68,
+ 0x10FBC: 68,
+ 0x10FBD: 82,
+ 0x10FBE: 68,
+ 0x10FBF: 68,
+ 0x10FC1: 68,
+ 0x10FC2: 82,
+ 0x10FC3: 82,
+ 0x10FC4: 68,
+ 0x10FC9: 82,
+ 0x10FCA: 68,
+ 0x10FCB: 76,
0x11001: 84,
0x11038: 84,
0x11039: 84,
- 0x1103a: 84,
- 0x1103b: 84,
- 0x1103c: 84,
- 0x1103d: 84,
- 0x1103e: 84,
- 0x1103f: 84,
+ 0x1103A: 84,
+ 0x1103B: 84,
+ 0x1103C: 84,
+ 0x1103D: 84,
+ 0x1103E: 84,
+ 0x1103F: 84,
0x11040: 84,
0x11041: 84,
0x11042: 84,
@@ -1976,27 +1976,27 @@ joining_types = {
0x11070: 84,
0x11073: 84,
0x11074: 84,
- 0x1107f: 84,
+ 0x1107F: 84,
0x11080: 84,
0x11081: 84,
- 0x110b3: 84,
- 0x110b4: 84,
- 0x110b5: 84,
- 0x110b6: 84,
- 0x110b9: 84,
- 0x110ba: 84,
- 0x110c2: 84,
+ 0x110B3: 84,
+ 0x110B4: 84,
+ 0x110B5: 84,
+ 0x110B6: 84,
+ 0x110B9: 84,
+ 0x110BA: 84,
+ 0x110C2: 84,
0x11100: 84,
0x11101: 84,
0x11102: 84,
0x11127: 84,
0x11128: 84,
0x11129: 84,
- 0x1112a: 84,
- 0x1112b: 84,
- 0x1112d: 84,
- 0x1112e: 84,
- 0x1112f: 84,
+ 0x1112A: 84,
+ 0x1112B: 84,
+ 0x1112D: 84,
+ 0x1112E: 84,
+ 0x1112F: 84,
0x11130: 84,
0x11131: 84,
0x11132: 84,
@@ -2005,49 +2005,49 @@ joining_types = {
0x11173: 84,
0x11180: 84,
0x11181: 84,
- 0x111b6: 84,
- 0x111b7: 84,
- 0x111b8: 84,
- 0x111b9: 84,
- 0x111ba: 84,
- 0x111bb: 84,
- 0x111bc: 84,
- 0x111bd: 84,
- 0x111be: 84,
- 0x111c9: 84,
- 0x111ca: 84,
- 0x111cb: 84,
- 0x111cc: 84,
- 0x111cf: 84,
- 0x1122f: 84,
+ 0x111B6: 84,
+ 0x111B7: 84,
+ 0x111B8: 84,
+ 0x111B9: 84,
+ 0x111BA: 84,
+ 0x111BB: 84,
+ 0x111BC: 84,
+ 0x111BD: 84,
+ 0x111BE: 84,
+ 0x111C9: 84,
+ 0x111CA: 84,
+ 0x111CB: 84,
+ 0x111CC: 84,
+ 0x111CF: 84,
+ 0x1122F: 84,
0x11230: 84,
0x11231: 84,
0x11234: 84,
0x11236: 84,
0x11237: 84,
- 0x1123e: 84,
+ 0x1123E: 84,
0x11241: 84,
- 0x112df: 84,
- 0x112e3: 84,
- 0x112e4: 84,
- 0x112e5: 84,
- 0x112e6: 84,
- 0x112e7: 84,
- 0x112e8: 84,
- 0x112e9: 84,
- 0x112ea: 84,
+ 0x112DF: 84,
+ 0x112E3: 84,
+ 0x112E4: 84,
+ 0x112E5: 84,
+ 0x112E6: 84,
+ 0x112E7: 84,
+ 0x112E8: 84,
+ 0x112E9: 84,
+ 0x112EA: 84,
0x11300: 84,
0x11301: 84,
- 0x1133b: 84,
- 0x1133c: 84,
+ 0x1133B: 84,
+ 0x1133C: 84,
0x11340: 84,
0x11366: 84,
0x11367: 84,
0x11368: 84,
0x11369: 84,
- 0x1136a: 84,
- 0x1136b: 84,
- 0x1136c: 84,
+ 0x1136A: 84,
+ 0x1136B: 84,
+ 0x1136C: 84,
0x11370: 84,
0x11371: 84,
0x11372: 84,
@@ -2055,38 +2055,38 @@ joining_types = {
0x11374: 84,
0x11438: 84,
0x11439: 84,
- 0x1143a: 84,
- 0x1143b: 84,
- 0x1143c: 84,
- 0x1143d: 84,
- 0x1143e: 84,
- 0x1143f: 84,
+ 0x1143A: 84,
+ 0x1143B: 84,
+ 0x1143C: 84,
+ 0x1143D: 84,
+ 0x1143E: 84,
+ 0x1143F: 84,
0x11442: 84,
0x11443: 84,
0x11444: 84,
0x11446: 84,
- 0x1145e: 84,
- 0x114b3: 84,
- 0x114b4: 84,
- 0x114b5: 84,
- 0x114b6: 84,
- 0x114b7: 84,
- 0x114b8: 84,
- 0x114ba: 84,
- 0x114bf: 84,
- 0x114c0: 84,
- 0x114c2: 84,
- 0x114c3: 84,
- 0x115b2: 84,
- 0x115b3: 84,
- 0x115b4: 84,
- 0x115b5: 84,
- 0x115bc: 84,
- 0x115bd: 84,
- 0x115bf: 84,
- 0x115c0: 84,
- 0x115dc: 84,
- 0x115dd: 84,
+ 0x1145E: 84,
+ 0x114B3: 84,
+ 0x114B4: 84,
+ 0x114B5: 84,
+ 0x114B6: 84,
+ 0x114B7: 84,
+ 0x114B8: 84,
+ 0x114BA: 84,
+ 0x114BF: 84,
+ 0x114C0: 84,
+ 0x114C2: 84,
+ 0x114C3: 84,
+ 0x115B2: 84,
+ 0x115B3: 84,
+ 0x115B4: 84,
+ 0x115B5: 84,
+ 0x115BC: 84,
+ 0x115BD: 84,
+ 0x115BF: 84,
+ 0x115C0: 84,
+ 0x115DC: 84,
+ 0x115DD: 84,
0x11633: 84,
0x11634: 84,
0x11635: 84,
@@ -2094,22 +2094,22 @@ joining_types = {
0x11637: 84,
0x11638: 84,
0x11639: 84,
- 0x1163a: 84,
- 0x1163d: 84,
- 0x1163f: 84,
+ 0x1163A: 84,
+ 0x1163D: 84,
+ 0x1163F: 84,
0x11640: 84,
- 0x116ab: 84,
- 0x116ad: 84,
- 0x116b0: 84,
- 0x116b1: 84,
- 0x116b2: 84,
- 0x116b3: 84,
- 0x116b4: 84,
- 0x116b5: 84,
- 0x116b7: 84,
- 0x1171d: 84,
- 0x1171e: 84,
- 0x1171f: 84,
+ 0x116AB: 84,
+ 0x116AD: 84,
+ 0x116B0: 84,
+ 0x116B1: 84,
+ 0x116B2: 84,
+ 0x116B3: 84,
+ 0x116B4: 84,
+ 0x116B5: 84,
+ 0x116B7: 84,
+ 0x1171D: 84,
+ 0x1171E: 84,
+ 0x1171F: 84,
0x11722: 84,
0x11723: 84,
0x11724: 84,
@@ -2117,9 +2117,9 @@ joining_types = {
0x11727: 84,
0x11728: 84,
0x11729: 84,
- 0x1172a: 84,
- 0x1172b: 84,
- 0x1182f: 84,
+ 0x1172A: 84,
+ 0x1172B: 84,
+ 0x1182F: 84,
0x11830: 84,
0x11831: 84,
0x11832: 84,
@@ -2129,142 +2129,142 @@ joining_types = {
0x11836: 84,
0x11837: 84,
0x11839: 84,
- 0x1183a: 84,
- 0x1193b: 84,
- 0x1193c: 84,
- 0x1193e: 84,
+ 0x1183A: 84,
+ 0x1193B: 84,
+ 0x1193C: 84,
+ 0x1193E: 84,
0x11943: 84,
- 0x119d4: 84,
- 0x119d5: 84,
- 0x119d6: 84,
- 0x119d7: 84,
- 0x119da: 84,
- 0x119db: 84,
- 0x119e0: 84,
- 0x11a01: 84,
- 0x11a02: 84,
- 0x11a03: 84,
- 0x11a04: 84,
- 0x11a05: 84,
- 0x11a06: 84,
- 0x11a07: 84,
- 0x11a08: 84,
- 0x11a09: 84,
- 0x11a0a: 84,
- 0x11a33: 84,
- 0x11a34: 84,
- 0x11a35: 84,
- 0x11a36: 84,
- 0x11a37: 84,
- 0x11a38: 84,
- 0x11a3b: 84,
- 0x11a3c: 84,
- 0x11a3d: 84,
- 0x11a3e: 84,
- 0x11a47: 84,
- 0x11a51: 84,
- 0x11a52: 84,
- 0x11a53: 84,
- 0x11a54: 84,
- 0x11a55: 84,
- 0x11a56: 84,
- 0x11a59: 84,
- 0x11a5a: 84,
- 0x11a5b: 84,
- 0x11a8a: 84,
- 0x11a8b: 84,
- 0x11a8c: 84,
- 0x11a8d: 84,
- 0x11a8e: 84,
- 0x11a8f: 84,
- 0x11a90: 84,
- 0x11a91: 84,
- 0x11a92: 84,
- 0x11a93: 84,
- 0x11a94: 84,
- 0x11a95: 84,
- 0x11a96: 84,
- 0x11a98: 84,
- 0x11a99: 84,
- 0x11c30: 84,
- 0x11c31: 84,
- 0x11c32: 84,
- 0x11c33: 84,
- 0x11c34: 84,
- 0x11c35: 84,
- 0x11c36: 84,
- 0x11c38: 84,
- 0x11c39: 84,
- 0x11c3a: 84,
- 0x11c3b: 84,
- 0x11c3c: 84,
- 0x11c3d: 84,
- 0x11c3f: 84,
- 0x11c92: 84,
- 0x11c93: 84,
- 0x11c94: 84,
- 0x11c95: 84,
- 0x11c96: 84,
- 0x11c97: 84,
- 0x11c98: 84,
- 0x11c99: 84,
- 0x11c9a: 84,
- 0x11c9b: 84,
- 0x11c9c: 84,
- 0x11c9d: 84,
- 0x11c9e: 84,
- 0x11c9f: 84,
- 0x11ca0: 84,
- 0x11ca1: 84,
- 0x11ca2: 84,
- 0x11ca3: 84,
- 0x11ca4: 84,
- 0x11ca5: 84,
- 0x11ca6: 84,
- 0x11ca7: 84,
- 0x11caa: 84,
- 0x11cab: 84,
- 0x11cac: 84,
- 0x11cad: 84,
- 0x11cae: 84,
- 0x11caf: 84,
- 0x11cb0: 84,
- 0x11cb2: 84,
- 0x11cb3: 84,
- 0x11cb5: 84,
- 0x11cb6: 84,
- 0x11d31: 84,
- 0x11d32: 84,
- 0x11d33: 84,
- 0x11d34: 84,
- 0x11d35: 84,
- 0x11d36: 84,
- 0x11d3a: 84,
- 0x11d3c: 84,
- 0x11d3d: 84,
- 0x11d3f: 84,
- 0x11d40: 84,
- 0x11d41: 84,
- 0x11d42: 84,
- 0x11d43: 84,
- 0x11d44: 84,
- 0x11d45: 84,
- 0x11d47: 84,
- 0x11d90: 84,
- 0x11d91: 84,
- 0x11d95: 84,
- 0x11d97: 84,
- 0x11ef3: 84,
- 0x11ef4: 84,
- 0x11f00: 84,
- 0x11f01: 84,
- 0x11f36: 84,
- 0x11f37: 84,
- 0x11f38: 84,
- 0x11f39: 84,
- 0x11f3a: 84,
- 0x11f40: 84,
- 0x11f42: 84,
+ 0x119D4: 84,
+ 0x119D5: 84,
+ 0x119D6: 84,
+ 0x119D7: 84,
+ 0x119DA: 84,
+ 0x119DB: 84,
+ 0x119E0: 84,
+ 0x11A01: 84,
+ 0x11A02: 84,
+ 0x11A03: 84,
+ 0x11A04: 84,
+ 0x11A05: 84,
+ 0x11A06: 84,
+ 0x11A07: 84,
+ 0x11A08: 84,
+ 0x11A09: 84,
+ 0x11A0A: 84,
+ 0x11A33: 84,
+ 0x11A34: 84,
+ 0x11A35: 84,
+ 0x11A36: 84,
+ 0x11A37: 84,
+ 0x11A38: 84,
+ 0x11A3B: 84,
+ 0x11A3C: 84,
+ 0x11A3D: 84,
+ 0x11A3E: 84,
+ 0x11A47: 84,
+ 0x11A51: 84,
+ 0x11A52: 84,
+ 0x11A53: 84,
+ 0x11A54: 84,
+ 0x11A55: 84,
+ 0x11A56: 84,
+ 0x11A59: 84,
+ 0x11A5A: 84,
+ 0x11A5B: 84,
+ 0x11A8A: 84,
+ 0x11A8B: 84,
+ 0x11A8C: 84,
+ 0x11A8D: 84,
+ 0x11A8E: 84,
+ 0x11A8F: 84,
+ 0x11A90: 84,
+ 0x11A91: 84,
+ 0x11A92: 84,
+ 0x11A93: 84,
+ 0x11A94: 84,
+ 0x11A95: 84,
+ 0x11A96: 84,
+ 0x11A98: 84,
+ 0x11A99: 84,
+ 0x11C30: 84,
+ 0x11C31: 84,
+ 0x11C32: 84,
+ 0x11C33: 84,
+ 0x11C34: 84,
+ 0x11C35: 84,
+ 0x11C36: 84,
+ 0x11C38: 84,
+ 0x11C39: 84,
+ 0x11C3A: 84,
+ 0x11C3B: 84,
+ 0x11C3C: 84,
+ 0x11C3D: 84,
+ 0x11C3F: 84,
+ 0x11C92: 84,
+ 0x11C93: 84,
+ 0x11C94: 84,
+ 0x11C95: 84,
+ 0x11C96: 84,
+ 0x11C97: 84,
+ 0x11C98: 84,
+ 0x11C99: 84,
+ 0x11C9A: 84,
+ 0x11C9B: 84,
+ 0x11C9C: 84,
+ 0x11C9D: 84,
+ 0x11C9E: 84,
+ 0x11C9F: 84,
+ 0x11CA0: 84,
+ 0x11CA1: 84,
+ 0x11CA2: 84,
+ 0x11CA3: 84,
+ 0x11CA4: 84,
+ 0x11CA5: 84,
+ 0x11CA6: 84,
+ 0x11CA7: 84,
+ 0x11CAA: 84,
+ 0x11CAB: 84,
+ 0x11CAC: 84,
+ 0x11CAD: 84,
+ 0x11CAE: 84,
+ 0x11CAF: 84,
+ 0x11CB0: 84,
+ 0x11CB2: 84,
+ 0x11CB3: 84,
+ 0x11CB5: 84,
+ 0x11CB6: 84,
+ 0x11D31: 84,
+ 0x11D32: 84,
+ 0x11D33: 84,
+ 0x11D34: 84,
+ 0x11D35: 84,
+ 0x11D36: 84,
+ 0x11D3A: 84,
+ 0x11D3C: 84,
+ 0x11D3D: 84,
+ 0x11D3F: 84,
+ 0x11D40: 84,
+ 0x11D41: 84,
+ 0x11D42: 84,
+ 0x11D43: 84,
+ 0x11D44: 84,
+ 0x11D45: 84,
+ 0x11D47: 84,
+ 0x11D90: 84,
+ 0x11D91: 84,
+ 0x11D95: 84,
+ 0x11D97: 84,
+ 0x11EF3: 84,
+ 0x11EF4: 84,
+ 0x11F00: 84,
+ 0x11F01: 84,
+ 0x11F36: 84,
+ 0x11F37: 84,
+ 0x11F38: 84,
+ 0x11F39: 84,
+ 0x11F3A: 84,
+ 0x11F40: 84,
+ 0x11F42: 84,
0x13430: 84,
0x13431: 84,
0x13432: 84,
@@ -2275,1971 +2275,1969 @@ joining_types = {
0x13437: 84,
0x13438: 84,
0x13439: 84,
- 0x1343a: 84,
- 0x1343b: 84,
- 0x1343c: 84,
- 0x1343d: 84,
- 0x1343e: 84,
- 0x1343f: 84,
+ 0x1343A: 84,
+ 0x1343B: 84,
+ 0x1343C: 84,
+ 0x1343D: 84,
+ 0x1343E: 84,
+ 0x1343F: 84,
0x13440: 84,
0x13447: 84,
0x13448: 84,
0x13449: 84,
- 0x1344a: 84,
- 0x1344b: 84,
- 0x1344c: 84,
- 0x1344d: 84,
- 0x1344e: 84,
- 0x1344f: 84,
+ 0x1344A: 84,
+ 0x1344B: 84,
+ 0x1344C: 84,
+ 0x1344D: 84,
+ 0x1344E: 84,
+ 0x1344F: 84,
0x13450: 84,
0x13451: 84,
0x13452: 84,
0x13453: 84,
0x13454: 84,
0x13455: 84,
- 0x16af0: 84,
- 0x16af1: 84,
- 0x16af2: 84,
- 0x16af3: 84,
- 0x16af4: 84,
- 0x16b30: 84,
- 0x16b31: 84,
- 0x16b32: 84,
- 0x16b33: 84,
- 0x16b34: 84,
- 0x16b35: 84,
- 0x16b36: 84,
- 0x16f4f: 84,
- 0x16f8f: 84,
- 0x16f90: 84,
- 0x16f91: 84,
- 0x16f92: 84,
- 0x16fe4: 84,
- 0x1bc9d: 84,
- 0x1bc9e: 84,
- 0x1bca0: 84,
- 0x1bca1: 84,
- 0x1bca2: 84,
- 0x1bca3: 84,
- 0x1cf00: 84,
- 0x1cf01: 84,
- 0x1cf02: 84,
- 0x1cf03: 84,
- 0x1cf04: 84,
- 0x1cf05: 84,
- 0x1cf06: 84,
- 0x1cf07: 84,
- 0x1cf08: 84,
- 0x1cf09: 84,
- 0x1cf0a: 84,
- 0x1cf0b: 84,
- 0x1cf0c: 84,
- 0x1cf0d: 84,
- 0x1cf0e: 84,
- 0x1cf0f: 84,
- 0x1cf10: 84,
- 0x1cf11: 84,
- 0x1cf12: 84,
- 0x1cf13: 84,
- 0x1cf14: 84,
- 0x1cf15: 84,
- 0x1cf16: 84,
- 0x1cf17: 84,
- 0x1cf18: 84,
- 0x1cf19: 84,
- 0x1cf1a: 84,
- 0x1cf1b: 84,
- 0x1cf1c: 84,
- 0x1cf1d: 84,
- 0x1cf1e: 84,
- 0x1cf1f: 84,
- 0x1cf20: 84,
- 0x1cf21: 84,
- 0x1cf22: 84,
- 0x1cf23: 84,
- 0x1cf24: 84,
- 0x1cf25: 84,
- 0x1cf26: 84,
- 0x1cf27: 84,
- 0x1cf28: 84,
- 0x1cf29: 84,
- 0x1cf2a: 84,
- 0x1cf2b: 84,
- 0x1cf2c: 84,
- 0x1cf2d: 84,
- 0x1cf30: 84,
- 0x1cf31: 84,
- 0x1cf32: 84,
- 0x1cf33: 84,
- 0x1cf34: 84,
- 0x1cf35: 84,
- 0x1cf36: 84,
- 0x1cf37: 84,
- 0x1cf38: 84,
- 0x1cf39: 84,
- 0x1cf3a: 84,
- 0x1cf3b: 84,
- 0x1cf3c: 84,
- 0x1cf3d: 84,
- 0x1cf3e: 84,
- 0x1cf3f: 84,
- 0x1cf40: 84,
- 0x1cf41: 84,
- 0x1cf42: 84,
- 0x1cf43: 84,
- 0x1cf44: 84,
- 0x1cf45: 84,
- 0x1cf46: 84,
- 0x1d167: 84,
- 0x1d168: 84,
- 0x1d169: 84,
- 0x1d173: 84,
- 0x1d174: 84,
- 0x1d175: 84,
- 0x1d176: 84,
- 0x1d177: 84,
- 0x1d178: 84,
- 0x1d179: 84,
- 0x1d17a: 84,
- 0x1d17b: 84,
- 0x1d17c: 84,
- 0x1d17d: 84,
- 0x1d17e: 84,
- 0x1d17f: 84,
- 0x1d180: 84,
- 0x1d181: 84,
- 0x1d182: 84,
- 0x1d185: 84,
- 0x1d186: 84,
- 0x1d187: 84,
- 0x1d188: 84,
- 0x1d189: 84,
- 0x1d18a: 84,
- 0x1d18b: 84,
- 0x1d1aa: 84,
- 0x1d1ab: 84,
- 0x1d1ac: 84,
- 0x1d1ad: 84,
- 0x1d242: 84,
- 0x1d243: 84,
- 0x1d244: 84,
- 0x1da00: 84,
- 0x1da01: 84,
- 0x1da02: 84,
- 0x1da03: 84,
- 0x1da04: 84,
- 0x1da05: 84,
- 0x1da06: 84,
- 0x1da07: 84,
- 0x1da08: 84,
- 0x1da09: 84,
- 0x1da0a: 84,
- 0x1da0b: 84,
- 0x1da0c: 84,
- 0x1da0d: 84,
- 0x1da0e: 84,
- 0x1da0f: 84,
- 0x1da10: 84,
- 0x1da11: 84,
- 0x1da12: 84,
- 0x1da13: 84,
- 0x1da14: 84,
- 0x1da15: 84,
- 0x1da16: 84,
- 0x1da17: 84,
- 0x1da18: 84,
- 0x1da19: 84,
- 0x1da1a: 84,
- 0x1da1b: 84,
- 0x1da1c: 84,
- 0x1da1d: 84,
- 0x1da1e: 84,
- 0x1da1f: 84,
- 0x1da20: 84,
- 0x1da21: 84,
- 0x1da22: 84,
- 0x1da23: 84,
- 0x1da24: 84,
- 0x1da25: 84,
- 0x1da26: 84,
- 0x1da27: 84,
- 0x1da28: 84,
- 0x1da29: 84,
- 0x1da2a: 84,
- 0x1da2b: 84,
- 0x1da2c: 84,
- 0x1da2d: 84,
- 0x1da2e: 84,
- 0x1da2f: 84,
- 0x1da30: 84,
- 0x1da31: 84,
- 0x1da32: 84,
- 0x1da33: 84,
- 0x1da34: 84,
- 0x1da35: 84,
- 0x1da36: 84,
- 0x1da3b: 84,
- 0x1da3c: 84,
- 0x1da3d: 84,
- 0x1da3e: 84,
- 0x1da3f: 84,
- 0x1da40: 84,
- 0x1da41: 84,
- 0x1da42: 84,
- 0x1da43: 84,
- 0x1da44: 84,
- 0x1da45: 84,
- 0x1da46: 84,
- 0x1da47: 84,
- 0x1da48: 84,
- 0x1da49: 84,
- 0x1da4a: 84,
- 0x1da4b: 84,
- 0x1da4c: 84,
- 0x1da4d: 84,
- 0x1da4e: 84,
- 0x1da4f: 84,
- 0x1da50: 84,
- 0x1da51: 84,
- 0x1da52: 84,
- 0x1da53: 84,
- 0x1da54: 84,
- 0x1da55: 84,
- 0x1da56: 84,
- 0x1da57: 84,
- 0x1da58: 84,
- 0x1da59: 84,
- 0x1da5a: 84,
- 0x1da5b: 84,
- 0x1da5c: 84,
- 0x1da5d: 84,
- 0x1da5e: 84,
- 0x1da5f: 84,
- 0x1da60: 84,
- 0x1da61: 84,
- 0x1da62: 84,
- 0x1da63: 84,
- 0x1da64: 84,
- 0x1da65: 84,
- 0x1da66: 84,
- 0x1da67: 84,
- 0x1da68: 84,
- 0x1da69: 84,
- 0x1da6a: 84,
- 0x1da6b: 84,
- 0x1da6c: 84,
- 0x1da75: 84,
- 0x1da84: 84,
- 0x1da9b: 84,
- 0x1da9c: 84,
- 0x1da9d: 84,
- 0x1da9e: 84,
- 0x1da9f: 84,
- 0x1daa1: 84,
- 0x1daa2: 84,
- 0x1daa3: 84,
- 0x1daa4: 84,
- 0x1daa5: 84,
- 0x1daa6: 84,
- 0x1daa7: 84,
- 0x1daa8: 84,
- 0x1daa9: 84,
- 0x1daaa: 84,
- 0x1daab: 84,
- 0x1daac: 84,
- 0x1daad: 84,
- 0x1daae: 84,
- 0x1daaf: 84,
- 0x1e000: 84,
- 0x1e001: 84,
- 0x1e002: 84,
- 0x1e003: 84,
- 0x1e004: 84,
- 0x1e005: 84,
- 0x1e006: 84,
- 0x1e008: 84,
- 0x1e009: 84,
- 0x1e00a: 84,
- 0x1e00b: 84,
- 0x1e00c: 84,
- 0x1e00d: 84,
- 0x1e00e: 84,
- 0x1e00f: 84,
- 0x1e010: 84,
- 0x1e011: 84,
- 0x1e012: 84,
- 0x1e013: 84,
- 0x1e014: 84,
- 0x1e015: 84,
- 0x1e016: 84,
- 0x1e017: 84,
- 0x1e018: 84,
- 0x1e01b: 84,
- 0x1e01c: 84,
- 0x1e01d: 84,
- 0x1e01e: 84,
- 0x1e01f: 84,
- 0x1e020: 84,
- 0x1e021: 84,
- 0x1e023: 84,
- 0x1e024: 84,
- 0x1e026: 84,
- 0x1e027: 84,
- 0x1e028: 84,
- 0x1e029: 84,
- 0x1e02a: 84,
- 0x1e08f: 84,
- 0x1e130: 84,
- 0x1e131: 84,
- 0x1e132: 84,
- 0x1e133: 84,
- 0x1e134: 84,
- 0x1e135: 84,
- 0x1e136: 84,
- 0x1e2ae: 84,
- 0x1e2ec: 84,
- 0x1e2ed: 84,
- 0x1e2ee: 84,
- 0x1e2ef: 84,
- 0x1e4ec: 84,
- 0x1e4ed: 84,
- 0x1e4ee: 84,
- 0x1e4ef: 84,
- 0x1e8d0: 84,
- 0x1e8d1: 84,
- 0x1e8d2: 84,
- 0x1e8d3: 84,
- 0x1e8d4: 84,
- 0x1e8d5: 84,
- 0x1e8d6: 84,
- 0x1e900: 68,
- 0x1e901: 68,
- 0x1e902: 68,
- 0x1e903: 68,
- 0x1e904: 68,
- 0x1e905: 68,
- 0x1e906: 68,
- 0x1e907: 68,
- 0x1e908: 68,
- 0x1e909: 68,
- 0x1e90a: 68,
- 0x1e90b: 68,
- 0x1e90c: 68,
- 0x1e90d: 68,
- 0x1e90e: 68,
- 0x1e90f: 68,
- 0x1e910: 68,
- 0x1e911: 68,
- 0x1e912: 68,
- 0x1e913: 68,
- 0x1e914: 68,
- 0x1e915: 68,
- 0x1e916: 68,
- 0x1e917: 68,
- 0x1e918: 68,
- 0x1e919: 68,
- 0x1e91a: 68,
- 0x1e91b: 68,
- 0x1e91c: 68,
- 0x1e91d: 68,
- 0x1e91e: 68,
- 0x1e91f: 68,
- 0x1e920: 68,
- 0x1e921: 68,
- 0x1e922: 68,
- 0x1e923: 68,
- 0x1e924: 68,
- 0x1e925: 68,
- 0x1e926: 68,
- 0x1e927: 68,
- 0x1e928: 68,
- 0x1e929: 68,
- 0x1e92a: 68,
- 0x1e92b: 68,
- 0x1e92c: 68,
- 0x1e92d: 68,
- 0x1e92e: 68,
- 0x1e92f: 68,
- 0x1e930: 68,
- 0x1e931: 68,
- 0x1e932: 68,
- 0x1e933: 68,
- 0x1e934: 68,
- 0x1e935: 68,
- 0x1e936: 68,
- 0x1e937: 68,
- 0x1e938: 68,
- 0x1e939: 68,
- 0x1e93a: 68,
- 0x1e93b: 68,
- 0x1e93c: 68,
- 0x1e93d: 68,
- 0x1e93e: 68,
- 0x1e93f: 68,
- 0x1e940: 68,
- 0x1e941: 68,
- 0x1e942: 68,
- 0x1e943: 68,
- 0x1e944: 84,
- 0x1e945: 84,
- 0x1e946: 84,
- 0x1e947: 84,
- 0x1e948: 84,
- 0x1e949: 84,
- 0x1e94a: 84,
- 0x1e94b: 84,
- 0xe0001: 84,
- 0xe0020: 84,
- 0xe0021: 84,
- 0xe0022: 84,
- 0xe0023: 84,
- 0xe0024: 84,
- 0xe0025: 84,
- 0xe0026: 84,
- 0xe0027: 84,
- 0xe0028: 84,
- 0xe0029: 84,
- 0xe002a: 84,
- 0xe002b: 84,
- 0xe002c: 84,
- 0xe002d: 84,
- 0xe002e: 84,
- 0xe002f: 84,
- 0xe0030: 84,
- 0xe0031: 84,
- 0xe0032: 84,
- 0xe0033: 84,
- 0xe0034: 84,
- 0xe0035: 84,
- 0xe0036: 84,
- 0xe0037: 84,
- 0xe0038: 84,
- 0xe0039: 84,
- 0xe003a: 84,
- 0xe003b: 84,
- 0xe003c: 84,
- 0xe003d: 84,
- 0xe003e: 84,
- 0xe003f: 84,
- 0xe0040: 84,
- 0xe0041: 84,
- 0xe0042: 84,
- 0xe0043: 84,
- 0xe0044: 84,
- 0xe0045: 84,
- 0xe0046: 84,
- 0xe0047: 84,
- 0xe0048: 84,
- 0xe0049: 84,
- 0xe004a: 84,
- 0xe004b: 84,
- 0xe004c: 84,
- 0xe004d: 84,
- 0xe004e: 84,
- 0xe004f: 84,
- 0xe0050: 84,
- 0xe0051: 84,
- 0xe0052: 84,
- 0xe0053: 84,
- 0xe0054: 84,
- 0xe0055: 84,
- 0xe0056: 84,
- 0xe0057: 84,
- 0xe0058: 84,
- 0xe0059: 84,
- 0xe005a: 84,
- 0xe005b: 84,
- 0xe005c: 84,
- 0xe005d: 84,
- 0xe005e: 84,
- 0xe005f: 84,
- 0xe0060: 84,
- 0xe0061: 84,
- 0xe0062: 84,
- 0xe0063: 84,
- 0xe0064: 84,
- 0xe0065: 84,
- 0xe0066: 84,
- 0xe0067: 84,
- 0xe0068: 84,
- 0xe0069: 84,
- 0xe006a: 84,
- 0xe006b: 84,
- 0xe006c: 84,
- 0xe006d: 84,
- 0xe006e: 84,
- 0xe006f: 84,
- 0xe0070: 84,
- 0xe0071: 84,
- 0xe0072: 84,
- 0xe0073: 84,
- 0xe0074: 84,
- 0xe0075: 84,
- 0xe0076: 84,
- 0xe0077: 84,
- 0xe0078: 84,
- 0xe0079: 84,
- 0xe007a: 84,
- 0xe007b: 84,
- 0xe007c: 84,
- 0xe007d: 84,
- 0xe007e: 84,
- 0xe007f: 84,
- 0xe0100: 84,
- 0xe0101: 84,
- 0xe0102: 84,
- 0xe0103: 84,
- 0xe0104: 84,
- 0xe0105: 84,
- 0xe0106: 84,
- 0xe0107: 84,
- 0xe0108: 84,
- 0xe0109: 84,
- 0xe010a: 84,
- 0xe010b: 84,
- 0xe010c: 84,
- 0xe010d: 84,
- 0xe010e: 84,
- 0xe010f: 84,
- 0xe0110: 84,
- 0xe0111: 84,
- 0xe0112: 84,
- 0xe0113: 84,
- 0xe0114: 84,
- 0xe0115: 84,
- 0xe0116: 84,
- 0xe0117: 84,
- 0xe0118: 84,
- 0xe0119: 84,
- 0xe011a: 84,
- 0xe011b: 84,
- 0xe011c: 84,
- 0xe011d: 84,
- 0xe011e: 84,
- 0xe011f: 84,
- 0xe0120: 84,
- 0xe0121: 84,
- 0xe0122: 84,
- 0xe0123: 84,
- 0xe0124: 84,
- 0xe0125: 84,
- 0xe0126: 84,
- 0xe0127: 84,
- 0xe0128: 84,
- 0xe0129: 84,
- 0xe012a: 84,
- 0xe012b: 84,
- 0xe012c: 84,
- 0xe012d: 84,
- 0xe012e: 84,
- 0xe012f: 84,
- 0xe0130: 84,
- 0xe0131: 84,
- 0xe0132: 84,
- 0xe0133: 84,
- 0xe0134: 84,
- 0xe0135: 84,
- 0xe0136: 84,
- 0xe0137: 84,
- 0xe0138: 84,
- 0xe0139: 84,
- 0xe013a: 84,
- 0xe013b: 84,
- 0xe013c: 84,
- 0xe013d: 84,
- 0xe013e: 84,
- 0xe013f: 84,
- 0xe0140: 84,
- 0xe0141: 84,
- 0xe0142: 84,
- 0xe0143: 84,
- 0xe0144: 84,
- 0xe0145: 84,
- 0xe0146: 84,
- 0xe0147: 84,
- 0xe0148: 84,
- 0xe0149: 84,
- 0xe014a: 84,
- 0xe014b: 84,
- 0xe014c: 84,
- 0xe014d: 84,
- 0xe014e: 84,
- 0xe014f: 84,
- 0xe0150: 84,
- 0xe0151: 84,
- 0xe0152: 84,
- 0xe0153: 84,
- 0xe0154: 84,
- 0xe0155: 84,
- 0xe0156: 84,
- 0xe0157: 84,
- 0xe0158: 84,
- 0xe0159: 84,
- 0xe015a: 84,
- 0xe015b: 84,
- 0xe015c: 84,
- 0xe015d: 84,
- 0xe015e: 84,
- 0xe015f: 84,
- 0xe0160: 84,
- 0xe0161: 84,
- 0xe0162: 84,
- 0xe0163: 84,
- 0xe0164: 84,
- 0xe0165: 84,
- 0xe0166: 84,
- 0xe0167: 84,
- 0xe0168: 84,
- 0xe0169: 84,
- 0xe016a: 84,
- 0xe016b: 84,
- 0xe016c: 84,
- 0xe016d: 84,
- 0xe016e: 84,
- 0xe016f: 84,
- 0xe0170: 84,
- 0xe0171: 84,
- 0xe0172: 84,
- 0xe0173: 84,
- 0xe0174: 84,
- 0xe0175: 84,
- 0xe0176: 84,
- 0xe0177: 84,
- 0xe0178: 84,
- 0xe0179: 84,
- 0xe017a: 84,
- 0xe017b: 84,
- 0xe017c: 84,
- 0xe017d: 84,
- 0xe017e: 84,
- 0xe017f: 84,
- 0xe0180: 84,
- 0xe0181: 84,
- 0xe0182: 84,
- 0xe0183: 84,
- 0xe0184: 84,
- 0xe0185: 84,
- 0xe0186: 84,
- 0xe0187: 84,
- 0xe0188: 84,
- 0xe0189: 84,
- 0xe018a: 84,
- 0xe018b: 84,
- 0xe018c: 84,
- 0xe018d: 84,
- 0xe018e: 84,
- 0xe018f: 84,
- 0xe0190: 84,
- 0xe0191: 84,
- 0xe0192: 84,
- 0xe0193: 84,
- 0xe0194: 84,
- 0xe0195: 84,
- 0xe0196: 84,
- 0xe0197: 84,
- 0xe0198: 84,
- 0xe0199: 84,
- 0xe019a: 84,
- 0xe019b: 84,
- 0xe019c: 84,
- 0xe019d: 84,
- 0xe019e: 84,
- 0xe019f: 84,
- 0xe01a0: 84,
- 0xe01a1: 84,
- 0xe01a2: 84,
- 0xe01a3: 84,
- 0xe01a4: 84,
- 0xe01a5: 84,
- 0xe01a6: 84,
- 0xe01a7: 84,
- 0xe01a8: 84,
- 0xe01a9: 84,
- 0xe01aa: 84,
- 0xe01ab: 84,
- 0xe01ac: 84,
- 0xe01ad: 84,
- 0xe01ae: 84,
- 0xe01af: 84,
- 0xe01b0: 84,
- 0xe01b1: 84,
- 0xe01b2: 84,
- 0xe01b3: 84,
- 0xe01b4: 84,
- 0xe01b5: 84,
- 0xe01b6: 84,
- 0xe01b7: 84,
- 0xe01b8: 84,
- 0xe01b9: 84,
- 0xe01ba: 84,
- 0xe01bb: 84,
- 0xe01bc: 84,
- 0xe01bd: 84,
- 0xe01be: 84,
- 0xe01bf: 84,
- 0xe01c0: 84,
- 0xe01c1: 84,
- 0xe01c2: 84,
- 0xe01c3: 84,
- 0xe01c4: 84,
- 0xe01c5: 84,
- 0xe01c6: 84,
- 0xe01c7: 84,
- 0xe01c8: 84,
- 0xe01c9: 84,
- 0xe01ca: 84,
- 0xe01cb: 84,
- 0xe01cc: 84,
- 0xe01cd: 84,
- 0xe01ce: 84,
- 0xe01cf: 84,
- 0xe01d0: 84,
- 0xe01d1: 84,
- 0xe01d2: 84,
- 0xe01d3: 84,
- 0xe01d4: 84,
- 0xe01d5: 84,
- 0xe01d6: 84,
- 0xe01d7: 84,
- 0xe01d8: 84,
- 0xe01d9: 84,
- 0xe01da: 84,
- 0xe01db: 84,
- 0xe01dc: 84,
- 0xe01dd: 84,
- 0xe01de: 84,
- 0xe01df: 84,
- 0xe01e0: 84,
- 0xe01e1: 84,
- 0xe01e2: 84,
- 0xe01e3: 84,
- 0xe01e4: 84,
- 0xe01e5: 84,
- 0xe01e6: 84,
- 0xe01e7: 84,
- 0xe01e8: 84,
- 0xe01e9: 84,
- 0xe01ea: 84,
- 0xe01eb: 84,
- 0xe01ec: 84,
- 0xe01ed: 84,
- 0xe01ee: 84,
- 0xe01ef: 84,
+ 0x16AF0: 84,
+ 0x16AF1: 84,
+ 0x16AF2: 84,
+ 0x16AF3: 84,
+ 0x16AF4: 84,
+ 0x16B30: 84,
+ 0x16B31: 84,
+ 0x16B32: 84,
+ 0x16B33: 84,
+ 0x16B34: 84,
+ 0x16B35: 84,
+ 0x16B36: 84,
+ 0x16F4F: 84,
+ 0x16F8F: 84,
+ 0x16F90: 84,
+ 0x16F91: 84,
+ 0x16F92: 84,
+ 0x16FE4: 84,
+ 0x1BC9D: 84,
+ 0x1BC9E: 84,
+ 0x1BCA0: 84,
+ 0x1BCA1: 84,
+ 0x1BCA2: 84,
+ 0x1BCA3: 84,
+ 0x1CF00: 84,
+ 0x1CF01: 84,
+ 0x1CF02: 84,
+ 0x1CF03: 84,
+ 0x1CF04: 84,
+ 0x1CF05: 84,
+ 0x1CF06: 84,
+ 0x1CF07: 84,
+ 0x1CF08: 84,
+ 0x1CF09: 84,
+ 0x1CF0A: 84,
+ 0x1CF0B: 84,
+ 0x1CF0C: 84,
+ 0x1CF0D: 84,
+ 0x1CF0E: 84,
+ 0x1CF0F: 84,
+ 0x1CF10: 84,
+ 0x1CF11: 84,
+ 0x1CF12: 84,
+ 0x1CF13: 84,
+ 0x1CF14: 84,
+ 0x1CF15: 84,
+ 0x1CF16: 84,
+ 0x1CF17: 84,
+ 0x1CF18: 84,
+ 0x1CF19: 84,
+ 0x1CF1A: 84,
+ 0x1CF1B: 84,
+ 0x1CF1C: 84,
+ 0x1CF1D: 84,
+ 0x1CF1E: 84,
+ 0x1CF1F: 84,
+ 0x1CF20: 84,
+ 0x1CF21: 84,
+ 0x1CF22: 84,
+ 0x1CF23: 84,
+ 0x1CF24: 84,
+ 0x1CF25: 84,
+ 0x1CF26: 84,
+ 0x1CF27: 84,
+ 0x1CF28: 84,
+ 0x1CF29: 84,
+ 0x1CF2A: 84,
+ 0x1CF2B: 84,
+ 0x1CF2C: 84,
+ 0x1CF2D: 84,
+ 0x1CF30: 84,
+ 0x1CF31: 84,
+ 0x1CF32: 84,
+ 0x1CF33: 84,
+ 0x1CF34: 84,
+ 0x1CF35: 84,
+ 0x1CF36: 84,
+ 0x1CF37: 84,
+ 0x1CF38: 84,
+ 0x1CF39: 84,
+ 0x1CF3A: 84,
+ 0x1CF3B: 84,
+ 0x1CF3C: 84,
+ 0x1CF3D: 84,
+ 0x1CF3E: 84,
+ 0x1CF3F: 84,
+ 0x1CF40: 84,
+ 0x1CF41: 84,
+ 0x1CF42: 84,
+ 0x1CF43: 84,
+ 0x1CF44: 84,
+ 0x1CF45: 84,
+ 0x1CF46: 84,
+ 0x1D167: 84,
+ 0x1D168: 84,
+ 0x1D169: 84,
+ 0x1D173: 84,
+ 0x1D174: 84,
+ 0x1D175: 84,
+ 0x1D176: 84,
+ 0x1D177: 84,
+ 0x1D178: 84,
+ 0x1D179: 84,
+ 0x1D17A: 84,
+ 0x1D17B: 84,
+ 0x1D17C: 84,
+ 0x1D17D: 84,
+ 0x1D17E: 84,
+ 0x1D17F: 84,
+ 0x1D180: 84,
+ 0x1D181: 84,
+ 0x1D182: 84,
+ 0x1D185: 84,
+ 0x1D186: 84,
+ 0x1D187: 84,
+ 0x1D188: 84,
+ 0x1D189: 84,
+ 0x1D18A: 84,
+ 0x1D18B: 84,
+ 0x1D1AA: 84,
+ 0x1D1AB: 84,
+ 0x1D1AC: 84,
+ 0x1D1AD: 84,
+ 0x1D242: 84,
+ 0x1D243: 84,
+ 0x1D244: 84,
+ 0x1DA00: 84,
+ 0x1DA01: 84,
+ 0x1DA02: 84,
+ 0x1DA03: 84,
+ 0x1DA04: 84,
+ 0x1DA05: 84,
+ 0x1DA06: 84,
+ 0x1DA07: 84,
+ 0x1DA08: 84,
+ 0x1DA09: 84,
+ 0x1DA0A: 84,
+ 0x1DA0B: 84,
+ 0x1DA0C: 84,
+ 0x1DA0D: 84,
+ 0x1DA0E: 84,
+ 0x1DA0F: 84,
+ 0x1DA10: 84,
+ 0x1DA11: 84,
+ 0x1DA12: 84,
+ 0x1DA13: 84,
+ 0x1DA14: 84,
+ 0x1DA15: 84,
+ 0x1DA16: 84,
+ 0x1DA17: 84,
+ 0x1DA18: 84,
+ 0x1DA19: 84,
+ 0x1DA1A: 84,
+ 0x1DA1B: 84,
+ 0x1DA1C: 84,
+ 0x1DA1D: 84,
+ 0x1DA1E: 84,
+ 0x1DA1F: 84,
+ 0x1DA20: 84,
+ 0x1DA21: 84,
+ 0x1DA22: 84,
+ 0x1DA23: 84,
+ 0x1DA24: 84,
+ 0x1DA25: 84,
+ 0x1DA26: 84,
+ 0x1DA27: 84,
+ 0x1DA28: 84,
+ 0x1DA29: 84,
+ 0x1DA2A: 84,
+ 0x1DA2B: 84,
+ 0x1DA2C: 84,
+ 0x1DA2D: 84,
+ 0x1DA2E: 84,
+ 0x1DA2F: 84,
+ 0x1DA30: 84,
+ 0x1DA31: 84,
+ 0x1DA32: 84,
+ 0x1DA33: 84,
+ 0x1DA34: 84,
+ 0x1DA35: 84,
+ 0x1DA36: 84,
+ 0x1DA3B: 84,
+ 0x1DA3C: 84,
+ 0x1DA3D: 84,
+ 0x1DA3E: 84,
+ 0x1DA3F: 84,
+ 0x1DA40: 84,
+ 0x1DA41: 84,
+ 0x1DA42: 84,
+ 0x1DA43: 84,
+ 0x1DA44: 84,
+ 0x1DA45: 84,
+ 0x1DA46: 84,
+ 0x1DA47: 84,
+ 0x1DA48: 84,
+ 0x1DA49: 84,
+ 0x1DA4A: 84,
+ 0x1DA4B: 84,
+ 0x1DA4C: 84,
+ 0x1DA4D: 84,
+ 0x1DA4E: 84,
+ 0x1DA4F: 84,
+ 0x1DA50: 84,
+ 0x1DA51: 84,
+ 0x1DA52: 84,
+ 0x1DA53: 84,
+ 0x1DA54: 84,
+ 0x1DA55: 84,
+ 0x1DA56: 84,
+ 0x1DA57: 84,
+ 0x1DA58: 84,
+ 0x1DA59: 84,
+ 0x1DA5A: 84,
+ 0x1DA5B: 84,
+ 0x1DA5C: 84,
+ 0x1DA5D: 84,
+ 0x1DA5E: 84,
+ 0x1DA5F: 84,
+ 0x1DA60: 84,
+ 0x1DA61: 84,
+ 0x1DA62: 84,
+ 0x1DA63: 84,
+ 0x1DA64: 84,
+ 0x1DA65: 84,
+ 0x1DA66: 84,
+ 0x1DA67: 84,
+ 0x1DA68: 84,
+ 0x1DA69: 84,
+ 0x1DA6A: 84,
+ 0x1DA6B: 84,
+ 0x1DA6C: 84,
+ 0x1DA75: 84,
+ 0x1DA84: 84,
+ 0x1DA9B: 84,
+ 0x1DA9C: 84,
+ 0x1DA9D: 84,
+ 0x1DA9E: 84,
+ 0x1DA9F: 84,
+ 0x1DAA1: 84,
+ 0x1DAA2: 84,
+ 0x1DAA3: 84,
+ 0x1DAA4: 84,
+ 0x1DAA5: 84,
+ 0x1DAA6: 84,
+ 0x1DAA7: 84,
+ 0x1DAA8: 84,
+ 0x1DAA9: 84,
+ 0x1DAAA: 84,
+ 0x1DAAB: 84,
+ 0x1DAAC: 84,
+ 0x1DAAD: 84,
+ 0x1DAAE: 84,
+ 0x1DAAF: 84,
+ 0x1E000: 84,
+ 0x1E001: 84,
+ 0x1E002: 84,
+ 0x1E003: 84,
+ 0x1E004: 84,
+ 0x1E005: 84,
+ 0x1E006: 84,
+ 0x1E008: 84,
+ 0x1E009: 84,
+ 0x1E00A: 84,
+ 0x1E00B: 84,
+ 0x1E00C: 84,
+ 0x1E00D: 84,
+ 0x1E00E: 84,
+ 0x1E00F: 84,
+ 0x1E010: 84,
+ 0x1E011: 84,
+ 0x1E012: 84,
+ 0x1E013: 84,
+ 0x1E014: 84,
+ 0x1E015: 84,
+ 0x1E016: 84,
+ 0x1E017: 84,
+ 0x1E018: 84,
+ 0x1E01B: 84,
+ 0x1E01C: 84,
+ 0x1E01D: 84,
+ 0x1E01E: 84,
+ 0x1E01F: 84,
+ 0x1E020: 84,
+ 0x1E021: 84,
+ 0x1E023: 84,
+ 0x1E024: 84,
+ 0x1E026: 84,
+ 0x1E027: 84,
+ 0x1E028: 84,
+ 0x1E029: 84,
+ 0x1E02A: 84,
+ 0x1E08F: 84,
+ 0x1E130: 84,
+ 0x1E131: 84,
+ 0x1E132: 84,
+ 0x1E133: 84,
+ 0x1E134: 84,
+ 0x1E135: 84,
+ 0x1E136: 84,
+ 0x1E2AE: 84,
+ 0x1E2EC: 84,
+ 0x1E2ED: 84,
+ 0x1E2EE: 84,
+ 0x1E2EF: 84,
+ 0x1E4EC: 84,
+ 0x1E4ED: 84,
+ 0x1E4EE: 84,
+ 0x1E4EF: 84,
+ 0x1E8D0: 84,
+ 0x1E8D1: 84,
+ 0x1E8D2: 84,
+ 0x1E8D3: 84,
+ 0x1E8D4: 84,
+ 0x1E8D5: 84,
+ 0x1E8D6: 84,
+ 0x1E900: 68,
+ 0x1E901: 68,
+ 0x1E902: 68,
+ 0x1E903: 68,
+ 0x1E904: 68,
+ 0x1E905: 68,
+ 0x1E906: 68,
+ 0x1E907: 68,
+ 0x1E908: 68,
+ 0x1E909: 68,
+ 0x1E90A: 68,
+ 0x1E90B: 68,
+ 0x1E90C: 68,
+ 0x1E90D: 68,
+ 0x1E90E: 68,
+ 0x1E90F: 68,
+ 0x1E910: 68,
+ 0x1E911: 68,
+ 0x1E912: 68,
+ 0x1E913: 68,
+ 0x1E914: 68,
+ 0x1E915: 68,
+ 0x1E916: 68,
+ 0x1E917: 68,
+ 0x1E918: 68,
+ 0x1E919: 68,
+ 0x1E91A: 68,
+ 0x1E91B: 68,
+ 0x1E91C: 68,
+ 0x1E91D: 68,
+ 0x1E91E: 68,
+ 0x1E91F: 68,
+ 0x1E920: 68,
+ 0x1E921: 68,
+ 0x1E922: 68,
+ 0x1E923: 68,
+ 0x1E924: 68,
+ 0x1E925: 68,
+ 0x1E926: 68,
+ 0x1E927: 68,
+ 0x1E928: 68,
+ 0x1E929: 68,
+ 0x1E92A: 68,
+ 0x1E92B: 68,
+ 0x1E92C: 68,
+ 0x1E92D: 68,
+ 0x1E92E: 68,
+ 0x1E92F: 68,
+ 0x1E930: 68,
+ 0x1E931: 68,
+ 0x1E932: 68,
+ 0x1E933: 68,
+ 0x1E934: 68,
+ 0x1E935: 68,
+ 0x1E936: 68,
+ 0x1E937: 68,
+ 0x1E938: 68,
+ 0x1E939: 68,
+ 0x1E93A: 68,
+ 0x1E93B: 68,
+ 0x1E93C: 68,
+ 0x1E93D: 68,
+ 0x1E93E: 68,
+ 0x1E93F: 68,
+ 0x1E940: 68,
+ 0x1E941: 68,
+ 0x1E942: 68,
+ 0x1E943: 68,
+ 0x1E944: 84,
+ 0x1E945: 84,
+ 0x1E946: 84,
+ 0x1E947: 84,
+ 0x1E948: 84,
+ 0x1E949: 84,
+ 0x1E94A: 84,
+ 0x1E94B: 84,
+ 0xE0001: 84,
+ 0xE0020: 84,
+ 0xE0021: 84,
+ 0xE0022: 84,
+ 0xE0023: 84,
+ 0xE0024: 84,
+ 0xE0025: 84,
+ 0xE0026: 84,
+ 0xE0027: 84,
+ 0xE0028: 84,
+ 0xE0029: 84,
+ 0xE002A: 84,
+ 0xE002B: 84,
+ 0xE002C: 84,
+ 0xE002D: 84,
+ 0xE002E: 84,
+ 0xE002F: 84,
+ 0xE0030: 84,
+ 0xE0031: 84,
+ 0xE0032: 84,
+ 0xE0033: 84,
+ 0xE0034: 84,
+ 0xE0035: 84,
+ 0xE0036: 84,
+ 0xE0037: 84,
+ 0xE0038: 84,
+ 0xE0039: 84,
+ 0xE003A: 84,
+ 0xE003B: 84,
+ 0xE003C: 84,
+ 0xE003D: 84,
+ 0xE003E: 84,
+ 0xE003F: 84,
+ 0xE0040: 84,
+ 0xE0041: 84,
+ 0xE0042: 84,
+ 0xE0043: 84,
+ 0xE0044: 84,
+ 0xE0045: 84,
+ 0xE0046: 84,
+ 0xE0047: 84,
+ 0xE0048: 84,
+ 0xE0049: 84,
+ 0xE004A: 84,
+ 0xE004B: 84,
+ 0xE004C: 84,
+ 0xE004D: 84,
+ 0xE004E: 84,
+ 0xE004F: 84,
+ 0xE0050: 84,
+ 0xE0051: 84,
+ 0xE0052: 84,
+ 0xE0053: 84,
+ 0xE0054: 84,
+ 0xE0055: 84,
+ 0xE0056: 84,
+ 0xE0057: 84,
+ 0xE0058: 84,
+ 0xE0059: 84,
+ 0xE005A: 84,
+ 0xE005B: 84,
+ 0xE005C: 84,
+ 0xE005D: 84,
+ 0xE005E: 84,
+ 0xE005F: 84,
+ 0xE0060: 84,
+ 0xE0061: 84,
+ 0xE0062: 84,
+ 0xE0063: 84,
+ 0xE0064: 84,
+ 0xE0065: 84,
+ 0xE0066: 84,
+ 0xE0067: 84,
+ 0xE0068: 84,
+ 0xE0069: 84,
+ 0xE006A: 84,
+ 0xE006B: 84,
+ 0xE006C: 84,
+ 0xE006D: 84,
+ 0xE006E: 84,
+ 0xE006F: 84,
+ 0xE0070: 84,
+ 0xE0071: 84,
+ 0xE0072: 84,
+ 0xE0073: 84,
+ 0xE0074: 84,
+ 0xE0075: 84,
+ 0xE0076: 84,
+ 0xE0077: 84,
+ 0xE0078: 84,
+ 0xE0079: 84,
+ 0xE007A: 84,
+ 0xE007B: 84,
+ 0xE007C: 84,
+ 0xE007D: 84,
+ 0xE007E: 84,
+ 0xE007F: 84,
+ 0xE0100: 84,
+ 0xE0101: 84,
+ 0xE0102: 84,
+ 0xE0103: 84,
+ 0xE0104: 84,
+ 0xE0105: 84,
+ 0xE0106: 84,
+ 0xE0107: 84,
+ 0xE0108: 84,
+ 0xE0109: 84,
+ 0xE010A: 84,
+ 0xE010B: 84,
+ 0xE010C: 84,
+ 0xE010D: 84,
+ 0xE010E: 84,
+ 0xE010F: 84,
+ 0xE0110: 84,
+ 0xE0111: 84,
+ 0xE0112: 84,
+ 0xE0113: 84,
+ 0xE0114: 84,
+ 0xE0115: 84,
+ 0xE0116: 84,
+ 0xE0117: 84,
+ 0xE0118: 84,
+ 0xE0119: 84,
+ 0xE011A: 84,
+ 0xE011B: 84,
+ 0xE011C: 84,
+ 0xE011D: 84,
+ 0xE011E: 84,
+ 0xE011F: 84,
+ 0xE0120: 84,
+ 0xE0121: 84,
+ 0xE0122: 84,
+ 0xE0123: 84,
+ 0xE0124: 84,
+ 0xE0125: 84,
+ 0xE0126: 84,
+ 0xE0127: 84,
+ 0xE0128: 84,
+ 0xE0129: 84,
+ 0xE012A: 84,
+ 0xE012B: 84,
+ 0xE012C: 84,
+ 0xE012D: 84,
+ 0xE012E: 84,
+ 0xE012F: 84,
+ 0xE0130: 84,
+ 0xE0131: 84,
+ 0xE0132: 84,
+ 0xE0133: 84,
+ 0xE0134: 84,
+ 0xE0135: 84,
+ 0xE0136: 84,
+ 0xE0137: 84,
+ 0xE0138: 84,
+ 0xE0139: 84,
+ 0xE013A: 84,
+ 0xE013B: 84,
+ 0xE013C: 84,
+ 0xE013D: 84,
+ 0xE013E: 84,
+ 0xE013F: 84,
+ 0xE0140: 84,
+ 0xE0141: 84,
+ 0xE0142: 84,
+ 0xE0143: 84,
+ 0xE0144: 84,
+ 0xE0145: 84,
+ 0xE0146: 84,
+ 0xE0147: 84,
+ 0xE0148: 84,
+ 0xE0149: 84,
+ 0xE014A: 84,
+ 0xE014B: 84,
+ 0xE014C: 84,
+ 0xE014D: 84,
+ 0xE014E: 84,
+ 0xE014F: 84,
+ 0xE0150: 84,
+ 0xE0151: 84,
+ 0xE0152: 84,
+ 0xE0153: 84,
+ 0xE0154: 84,
+ 0xE0155: 84,
+ 0xE0156: 84,
+ 0xE0157: 84,
+ 0xE0158: 84,
+ 0xE0159: 84,
+ 0xE015A: 84,
+ 0xE015B: 84,
+ 0xE015C: 84,
+ 0xE015D: 84,
+ 0xE015E: 84,
+ 0xE015F: 84,
+ 0xE0160: 84,
+ 0xE0161: 84,
+ 0xE0162: 84,
+ 0xE0163: 84,
+ 0xE0164: 84,
+ 0xE0165: 84,
+ 0xE0166: 84,
+ 0xE0167: 84,
+ 0xE0168: 84,
+ 0xE0169: 84,
+ 0xE016A: 84,
+ 0xE016B: 84,
+ 0xE016C: 84,
+ 0xE016D: 84,
+ 0xE016E: 84,
+ 0xE016F: 84,
+ 0xE0170: 84,
+ 0xE0171: 84,
+ 0xE0172: 84,
+ 0xE0173: 84,
+ 0xE0174: 84,
+ 0xE0175: 84,
+ 0xE0176: 84,
+ 0xE0177: 84,
+ 0xE0178: 84,
+ 0xE0179: 84,
+ 0xE017A: 84,
+ 0xE017B: 84,
+ 0xE017C: 84,
+ 0xE017D: 84,
+ 0xE017E: 84,
+ 0xE017F: 84,
+ 0xE0180: 84,
+ 0xE0181: 84,
+ 0xE0182: 84,
+ 0xE0183: 84,
+ 0xE0184: 84,
+ 0xE0185: 84,
+ 0xE0186: 84,
+ 0xE0187: 84,
+ 0xE0188: 84,
+ 0xE0189: 84,
+ 0xE018A: 84,
+ 0xE018B: 84,
+ 0xE018C: 84,
+ 0xE018D: 84,
+ 0xE018E: 84,
+ 0xE018F: 84,
+ 0xE0190: 84,
+ 0xE0191: 84,
+ 0xE0192: 84,
+ 0xE0193: 84,
+ 0xE0194: 84,
+ 0xE0195: 84,
+ 0xE0196: 84,
+ 0xE0197: 84,
+ 0xE0198: 84,
+ 0xE0199: 84,
+ 0xE019A: 84,
+ 0xE019B: 84,
+ 0xE019C: 84,
+ 0xE019D: 84,
+ 0xE019E: 84,
+ 0xE019F: 84,
+ 0xE01A0: 84,
+ 0xE01A1: 84,
+ 0xE01A2: 84,
+ 0xE01A3: 84,
+ 0xE01A4: 84,
+ 0xE01A5: 84,
+ 0xE01A6: 84,
+ 0xE01A7: 84,
+ 0xE01A8: 84,
+ 0xE01A9: 84,
+ 0xE01AA: 84,
+ 0xE01AB: 84,
+ 0xE01AC: 84,
+ 0xE01AD: 84,
+ 0xE01AE: 84,
+ 0xE01AF: 84,
+ 0xE01B0: 84,
+ 0xE01B1: 84,
+ 0xE01B2: 84,
+ 0xE01B3: 84,
+ 0xE01B4: 84,
+ 0xE01B5: 84,
+ 0xE01B6: 84,
+ 0xE01B7: 84,
+ 0xE01B8: 84,
+ 0xE01B9: 84,
+ 0xE01BA: 84,
+ 0xE01BB: 84,
+ 0xE01BC: 84,
+ 0xE01BD: 84,
+ 0xE01BE: 84,
+ 0xE01BF: 84,
+ 0xE01C0: 84,
+ 0xE01C1: 84,
+ 0xE01C2: 84,
+ 0xE01C3: 84,
+ 0xE01C4: 84,
+ 0xE01C5: 84,
+ 0xE01C6: 84,
+ 0xE01C7: 84,
+ 0xE01C8: 84,
+ 0xE01C9: 84,
+ 0xE01CA: 84,
+ 0xE01CB: 84,
+ 0xE01CC: 84,
+ 0xE01CD: 84,
+ 0xE01CE: 84,
+ 0xE01CF: 84,
+ 0xE01D0: 84,
+ 0xE01D1: 84,
+ 0xE01D2: 84,
+ 0xE01D3: 84,
+ 0xE01D4: 84,
+ 0xE01D5: 84,
+ 0xE01D6: 84,
+ 0xE01D7: 84,
+ 0xE01D8: 84,
+ 0xE01D9: 84,
+ 0xE01DA: 84,
+ 0xE01DB: 84,
+ 0xE01DC: 84,
+ 0xE01DD: 84,
+ 0xE01DE: 84,
+ 0xE01DF: 84,
+ 0xE01E0: 84,
+ 0xE01E1: 84,
+ 0xE01E2: 84,
+ 0xE01E3: 84,
+ 0xE01E4: 84,
+ 0xE01E5: 84,
+ 0xE01E6: 84,
+ 0xE01E7: 84,
+ 0xE01E8: 84,
+ 0xE01E9: 84,
+ 0xE01EA: 84,
+ 0xE01EB: 84,
+ 0xE01EC: 84,
+ 0xE01ED: 84,
+ 0xE01EE: 84,
+ 0xE01EF: 84,
}
codepoint_classes = {
- 'PVALID': (
- 0x2d0000002e,
- 0x300000003a,
- 0x610000007b,
- 0xdf000000f7,
- 0xf800000100,
+ "PVALID": (
+ 0x2D0000002E,
+ 0x300000003A,
+ 0x610000007B,
+ 0xDF000000F7,
+ 0xF800000100,
0x10100000102,
0x10300000104,
0x10500000106,
0x10700000108,
- 0x1090000010a,
- 0x10b0000010c,
- 0x10d0000010e,
- 0x10f00000110,
+ 0x1090000010A,
+ 0x10B0000010C,
+ 0x10D0000010E,
+ 0x10F00000110,
0x11100000112,
0x11300000114,
0x11500000116,
0x11700000118,
- 0x1190000011a,
- 0x11b0000011c,
- 0x11d0000011e,
- 0x11f00000120,
+ 0x1190000011A,
+ 0x11B0000011C,
+ 0x11D0000011E,
+ 0x11F00000120,
0x12100000122,
0x12300000124,
0x12500000126,
0x12700000128,
- 0x1290000012a,
- 0x12b0000012c,
- 0x12d0000012e,
- 0x12f00000130,
+ 0x1290000012A,
+ 0x12B0000012C,
+ 0x12D0000012E,
+ 0x12F00000130,
0x13100000132,
0x13500000136,
0x13700000139,
- 0x13a0000013b,
- 0x13c0000013d,
- 0x13e0000013f,
+ 0x13A0000013B,
+ 0x13C0000013D,
+ 0x13E0000013F,
0x14200000143,
0x14400000145,
0x14600000147,
0x14800000149,
- 0x14b0000014c,
- 0x14d0000014e,
- 0x14f00000150,
+ 0x14B0000014C,
+ 0x14D0000014E,
+ 0x14F00000150,
0x15100000152,
0x15300000154,
0x15500000156,
0x15700000158,
- 0x1590000015a,
- 0x15b0000015c,
- 0x15d0000015e,
- 0x15f00000160,
+ 0x1590000015A,
+ 0x15B0000015C,
+ 0x15D0000015E,
+ 0x15F00000160,
0x16100000162,
0x16300000164,
0x16500000166,
0x16700000168,
- 0x1690000016a,
- 0x16b0000016c,
- 0x16d0000016e,
- 0x16f00000170,
+ 0x1690000016A,
+ 0x16B0000016C,
+ 0x16D0000016E,
+ 0x16F00000170,
0x17100000172,
0x17300000174,
0x17500000176,
0x17700000178,
- 0x17a0000017b,
- 0x17c0000017d,
- 0x17e0000017f,
+ 0x17A0000017B,
+ 0x17C0000017D,
+ 0x17E0000017F,
0x18000000181,
0x18300000184,
0x18500000186,
0x18800000189,
- 0x18c0000018e,
+ 0x18C0000018E,
0x19200000193,
0x19500000196,
- 0x1990000019c,
- 0x19e0000019f,
- 0x1a1000001a2,
- 0x1a3000001a4,
- 0x1a5000001a6,
- 0x1a8000001a9,
- 0x1aa000001ac,
- 0x1ad000001ae,
- 0x1b0000001b1,
- 0x1b4000001b5,
- 0x1b6000001b7,
- 0x1b9000001bc,
- 0x1bd000001c4,
- 0x1ce000001cf,
- 0x1d0000001d1,
- 0x1d2000001d3,
- 0x1d4000001d5,
- 0x1d6000001d7,
- 0x1d8000001d9,
- 0x1da000001db,
- 0x1dc000001de,
- 0x1df000001e0,
- 0x1e1000001e2,
- 0x1e3000001e4,
- 0x1e5000001e6,
- 0x1e7000001e8,
- 0x1e9000001ea,
- 0x1eb000001ec,
- 0x1ed000001ee,
- 0x1ef000001f1,
- 0x1f5000001f6,
- 0x1f9000001fa,
- 0x1fb000001fc,
- 0x1fd000001fe,
- 0x1ff00000200,
+ 0x1990000019C,
+ 0x19E0000019F,
+ 0x1A1000001A2,
+ 0x1A3000001A4,
+ 0x1A5000001A6,
+ 0x1A8000001A9,
+ 0x1AA000001AC,
+ 0x1AD000001AE,
+ 0x1B0000001B1,
+ 0x1B4000001B5,
+ 0x1B6000001B7,
+ 0x1B9000001BC,
+ 0x1BD000001C4,
+ 0x1CE000001CF,
+ 0x1D0000001D1,
+ 0x1D2000001D3,
+ 0x1D4000001D5,
+ 0x1D6000001D7,
+ 0x1D8000001D9,
+ 0x1DA000001DB,
+ 0x1DC000001DE,
+ 0x1DF000001E0,
+ 0x1E1000001E2,
+ 0x1E3000001E4,
+ 0x1E5000001E6,
+ 0x1E7000001E8,
+ 0x1E9000001EA,
+ 0x1EB000001EC,
+ 0x1ED000001EE,
+ 0x1EF000001F1,
+ 0x1F5000001F6,
+ 0x1F9000001FA,
+ 0x1FB000001FC,
+ 0x1FD000001FE,
+ 0x1FF00000200,
0x20100000202,
0x20300000204,
0x20500000206,
0x20700000208,
- 0x2090000020a,
- 0x20b0000020c,
- 0x20d0000020e,
- 0x20f00000210,
+ 0x2090000020A,
+ 0x20B0000020C,
+ 0x20D0000020E,
+ 0x20F00000210,
0x21100000212,
0x21300000214,
0x21500000216,
0x21700000218,
- 0x2190000021a,
- 0x21b0000021c,
- 0x21d0000021e,
- 0x21f00000220,
+ 0x2190000021A,
+ 0x21B0000021C,
+ 0x21D0000021E,
+ 0x21F00000220,
0x22100000222,
0x22300000224,
0x22500000226,
0x22700000228,
- 0x2290000022a,
- 0x22b0000022c,
- 0x22d0000022e,
- 0x22f00000230,
+ 0x2290000022A,
+ 0x22B0000022C,
+ 0x22D0000022E,
+ 0x22F00000230,
0x23100000232,
- 0x2330000023a,
- 0x23c0000023d,
- 0x23f00000241,
+ 0x2330000023A,
+ 0x23C0000023D,
+ 0x23F00000241,
0x24200000243,
0x24700000248,
- 0x2490000024a,
- 0x24b0000024c,
- 0x24d0000024e,
- 0x24f000002b0,
- 0x2b9000002c2,
- 0x2c6000002d2,
- 0x2ec000002ed,
- 0x2ee000002ef,
+ 0x2490000024A,
+ 0x24B0000024C,
+ 0x24D0000024E,
+ 0x24F000002B0,
+ 0x2B9000002C2,
+ 0x2C6000002D2,
+ 0x2EC000002ED,
+ 0x2EE000002EF,
0x30000000340,
0x34200000343,
- 0x3460000034f,
+ 0x3460000034F,
0x35000000370,
0x37100000372,
0x37300000374,
0x37700000378,
- 0x37b0000037e,
+ 0x37B0000037E,
0x39000000391,
- 0x3ac000003cf,
- 0x3d7000003d8,
- 0x3d9000003da,
- 0x3db000003dc,
- 0x3dd000003de,
- 0x3df000003e0,
- 0x3e1000003e2,
- 0x3e3000003e4,
- 0x3e5000003e6,
- 0x3e7000003e8,
- 0x3e9000003ea,
- 0x3eb000003ec,
- 0x3ed000003ee,
- 0x3ef000003f0,
- 0x3f3000003f4,
- 0x3f8000003f9,
- 0x3fb000003fd,
+ 0x3AC000003CF,
+ 0x3D7000003D8,
+ 0x3D9000003DA,
+ 0x3DB000003DC,
+ 0x3DD000003DE,
+ 0x3DF000003E0,
+ 0x3E1000003E2,
+ 0x3E3000003E4,
+ 0x3E5000003E6,
+ 0x3E7000003E8,
+ 0x3E9000003EA,
+ 0x3EB000003EC,
+ 0x3ED000003EE,
+ 0x3EF000003F0,
+ 0x3F3000003F4,
+ 0x3F8000003F9,
+ 0x3FB000003FD,
0x43000000460,
0x46100000462,
0x46300000464,
0x46500000466,
0x46700000468,
- 0x4690000046a,
- 0x46b0000046c,
- 0x46d0000046e,
- 0x46f00000470,
+ 0x4690000046A,
+ 0x46B0000046C,
+ 0x46D0000046E,
+ 0x46F00000470,
0x47100000472,
0x47300000474,
0x47500000476,
0x47700000478,
- 0x4790000047a,
- 0x47b0000047c,
- 0x47d0000047e,
- 0x47f00000480,
+ 0x4790000047A,
+ 0x47B0000047C,
+ 0x47D0000047E,
+ 0x47F00000480,
0x48100000482,
0x48300000488,
- 0x48b0000048c,
- 0x48d0000048e,
- 0x48f00000490,
+ 0x48B0000048C,
+ 0x48D0000048E,
+ 0x48F00000490,
0x49100000492,
0x49300000494,
0x49500000496,
0x49700000498,
- 0x4990000049a,
- 0x49b0000049c,
- 0x49d0000049e,
- 0x49f000004a0,
- 0x4a1000004a2,
- 0x4a3000004a4,
- 0x4a5000004a6,
- 0x4a7000004a8,
- 0x4a9000004aa,
- 0x4ab000004ac,
- 0x4ad000004ae,
- 0x4af000004b0,
- 0x4b1000004b2,
- 0x4b3000004b4,
- 0x4b5000004b6,
- 0x4b7000004b8,
- 0x4b9000004ba,
- 0x4bb000004bc,
- 0x4bd000004be,
- 0x4bf000004c0,
- 0x4c2000004c3,
- 0x4c4000004c5,
- 0x4c6000004c7,
- 0x4c8000004c9,
- 0x4ca000004cb,
- 0x4cc000004cd,
- 0x4ce000004d0,
- 0x4d1000004d2,
- 0x4d3000004d4,
- 0x4d5000004d6,
- 0x4d7000004d8,
- 0x4d9000004da,
- 0x4db000004dc,
- 0x4dd000004de,
- 0x4df000004e0,
- 0x4e1000004e2,
- 0x4e3000004e4,
- 0x4e5000004e6,
- 0x4e7000004e8,
- 0x4e9000004ea,
- 0x4eb000004ec,
- 0x4ed000004ee,
- 0x4ef000004f0,
- 0x4f1000004f2,
- 0x4f3000004f4,
- 0x4f5000004f6,
- 0x4f7000004f8,
- 0x4f9000004fa,
- 0x4fb000004fc,
- 0x4fd000004fe,
- 0x4ff00000500,
+ 0x4990000049A,
+ 0x49B0000049C,
+ 0x49D0000049E,
+ 0x49F000004A0,
+ 0x4A1000004A2,
+ 0x4A3000004A4,
+ 0x4A5000004A6,
+ 0x4A7000004A8,
+ 0x4A9000004AA,
+ 0x4AB000004AC,
+ 0x4AD000004AE,
+ 0x4AF000004B0,
+ 0x4B1000004B2,
+ 0x4B3000004B4,
+ 0x4B5000004B6,
+ 0x4B7000004B8,
+ 0x4B9000004BA,
+ 0x4BB000004BC,
+ 0x4BD000004BE,
+ 0x4BF000004C0,
+ 0x4C2000004C3,
+ 0x4C4000004C5,
+ 0x4C6000004C7,
+ 0x4C8000004C9,
+ 0x4CA000004CB,
+ 0x4CC000004CD,
+ 0x4CE000004D0,
+ 0x4D1000004D2,
+ 0x4D3000004D4,
+ 0x4D5000004D6,
+ 0x4D7000004D8,
+ 0x4D9000004DA,
+ 0x4DB000004DC,
+ 0x4DD000004DE,
+ 0x4DF000004E0,
+ 0x4E1000004E2,
+ 0x4E3000004E4,
+ 0x4E5000004E6,
+ 0x4E7000004E8,
+ 0x4E9000004EA,
+ 0x4EB000004EC,
+ 0x4ED000004EE,
+ 0x4EF000004F0,
+ 0x4F1000004F2,
+ 0x4F3000004F4,
+ 0x4F5000004F6,
+ 0x4F7000004F8,
+ 0x4F9000004FA,
+ 0x4FB000004FC,
+ 0x4FD000004FE,
+ 0x4FF00000500,
0x50100000502,
0x50300000504,
0x50500000506,
0x50700000508,
- 0x5090000050a,
- 0x50b0000050c,
- 0x50d0000050e,
- 0x50f00000510,
+ 0x5090000050A,
+ 0x50B0000050C,
+ 0x50D0000050E,
+ 0x50F00000510,
0x51100000512,
0x51300000514,
0x51500000516,
0x51700000518,
- 0x5190000051a,
- 0x51b0000051c,
- 0x51d0000051e,
- 0x51f00000520,
+ 0x5190000051A,
+ 0x51B0000051C,
+ 0x51D0000051E,
+ 0x51F00000520,
0x52100000522,
0x52300000524,
0x52500000526,
0x52700000528,
- 0x5290000052a,
- 0x52b0000052c,
- 0x52d0000052e,
- 0x52f00000530,
- 0x5590000055a,
+ 0x5290000052A,
+ 0x52B0000052C,
+ 0x52D0000052E,
+ 0x52F00000530,
+ 0x5590000055A,
0x56000000587,
0x58800000589,
- 0x591000005be,
- 0x5bf000005c0,
- 0x5c1000005c3,
- 0x5c4000005c6,
- 0x5c7000005c8,
- 0x5d0000005eb,
- 0x5ef000005f3,
- 0x6100000061b,
+ 0x591000005BE,
+ 0x5BF000005C0,
+ 0x5C1000005C3,
+ 0x5C4000005C6,
+ 0x5C7000005C8,
+ 0x5D0000005EB,
+ 0x5EF000005F3,
+ 0x6100000061B,
0x62000000640,
0x64100000660,
- 0x66e00000675,
- 0x679000006d4,
- 0x6d5000006dd,
- 0x6df000006e9,
- 0x6ea000006f0,
- 0x6fa00000700,
- 0x7100000074b,
- 0x74d000007b2,
- 0x7c0000007f6,
- 0x7fd000007fe,
- 0x8000000082e,
- 0x8400000085c,
- 0x8600000086b,
+ 0x66E00000675,
+ 0x679000006D4,
+ 0x6D5000006DD,
+ 0x6DF000006E9,
+ 0x6EA000006F0,
+ 0x6FA00000700,
+ 0x7100000074B,
+ 0x74D000007B2,
+ 0x7C0000007F6,
+ 0x7FD000007FE,
+ 0x8000000082E,
+ 0x8400000085C,
+ 0x8600000086B,
0x87000000888,
- 0x8890000088f,
- 0x898000008e2,
- 0x8e300000958,
+ 0x8890000088F,
+ 0x898000008E2,
+ 0x8E300000958,
0x96000000964,
0x96600000970,
0x97100000984,
- 0x9850000098d,
- 0x98f00000991,
- 0x993000009a9,
- 0x9aa000009b1,
- 0x9b2000009b3,
- 0x9b6000009ba,
- 0x9bc000009c5,
- 0x9c7000009c9,
- 0x9cb000009cf,
- 0x9d7000009d8,
- 0x9e0000009e4,
- 0x9e6000009f2,
- 0x9fc000009fd,
- 0x9fe000009ff,
- 0xa0100000a04,
- 0xa0500000a0b,
- 0xa0f00000a11,
- 0xa1300000a29,
- 0xa2a00000a31,
- 0xa3200000a33,
- 0xa3500000a36,
- 0xa3800000a3a,
- 0xa3c00000a3d,
- 0xa3e00000a43,
- 0xa4700000a49,
- 0xa4b00000a4e,
- 0xa5100000a52,
- 0xa5c00000a5d,
- 0xa6600000a76,
- 0xa8100000a84,
- 0xa8500000a8e,
- 0xa8f00000a92,
- 0xa9300000aa9,
- 0xaaa00000ab1,
- 0xab200000ab4,
- 0xab500000aba,
- 0xabc00000ac6,
- 0xac700000aca,
- 0xacb00000ace,
- 0xad000000ad1,
- 0xae000000ae4,
- 0xae600000af0,
- 0xaf900000b00,
- 0xb0100000b04,
- 0xb0500000b0d,
- 0xb0f00000b11,
- 0xb1300000b29,
- 0xb2a00000b31,
- 0xb3200000b34,
- 0xb3500000b3a,
- 0xb3c00000b45,
- 0xb4700000b49,
- 0xb4b00000b4e,
- 0xb5500000b58,
- 0xb5f00000b64,
- 0xb6600000b70,
- 0xb7100000b72,
- 0xb8200000b84,
- 0xb8500000b8b,
- 0xb8e00000b91,
- 0xb9200000b96,
- 0xb9900000b9b,
- 0xb9c00000b9d,
- 0xb9e00000ba0,
- 0xba300000ba5,
- 0xba800000bab,
- 0xbae00000bba,
- 0xbbe00000bc3,
- 0xbc600000bc9,
- 0xbca00000bce,
- 0xbd000000bd1,
- 0xbd700000bd8,
- 0xbe600000bf0,
- 0xc0000000c0d,
- 0xc0e00000c11,
- 0xc1200000c29,
- 0xc2a00000c3a,
- 0xc3c00000c45,
- 0xc4600000c49,
- 0xc4a00000c4e,
- 0xc5500000c57,
- 0xc5800000c5b,
- 0xc5d00000c5e,
- 0xc6000000c64,
- 0xc6600000c70,
- 0xc8000000c84,
- 0xc8500000c8d,
- 0xc8e00000c91,
- 0xc9200000ca9,
- 0xcaa00000cb4,
- 0xcb500000cba,
- 0xcbc00000cc5,
- 0xcc600000cc9,
- 0xcca00000cce,
- 0xcd500000cd7,
- 0xcdd00000cdf,
- 0xce000000ce4,
- 0xce600000cf0,
- 0xcf100000cf4,
- 0xd0000000d0d,
- 0xd0e00000d11,
- 0xd1200000d45,
- 0xd4600000d49,
- 0xd4a00000d4f,
- 0xd5400000d58,
- 0xd5f00000d64,
- 0xd6600000d70,
- 0xd7a00000d80,
- 0xd8100000d84,
- 0xd8500000d97,
- 0xd9a00000db2,
- 0xdb300000dbc,
- 0xdbd00000dbe,
- 0xdc000000dc7,
- 0xdca00000dcb,
- 0xdcf00000dd5,
- 0xdd600000dd7,
- 0xdd800000de0,
- 0xde600000df0,
- 0xdf200000df4,
- 0xe0100000e33,
- 0xe3400000e3b,
- 0xe4000000e4f,
- 0xe5000000e5a,
- 0xe8100000e83,
- 0xe8400000e85,
- 0xe8600000e8b,
- 0xe8c00000ea4,
- 0xea500000ea6,
- 0xea700000eb3,
- 0xeb400000ebe,
- 0xec000000ec5,
- 0xec600000ec7,
- 0xec800000ecf,
- 0xed000000eda,
- 0xede00000ee0,
- 0xf0000000f01,
- 0xf0b00000f0c,
- 0xf1800000f1a,
- 0xf2000000f2a,
- 0xf3500000f36,
- 0xf3700000f38,
- 0xf3900000f3a,
- 0xf3e00000f43,
- 0xf4400000f48,
- 0xf4900000f4d,
- 0xf4e00000f52,
- 0xf5300000f57,
- 0xf5800000f5c,
- 0xf5d00000f69,
- 0xf6a00000f6d,
- 0xf7100000f73,
- 0xf7400000f75,
- 0xf7a00000f81,
- 0xf8200000f85,
- 0xf8600000f93,
- 0xf9400000f98,
- 0xf9900000f9d,
- 0xf9e00000fa2,
- 0xfa300000fa7,
- 0xfa800000fac,
- 0xfad00000fb9,
- 0xfba00000fbd,
- 0xfc600000fc7,
- 0x10000000104a,
- 0x10500000109e,
- 0x10d0000010fb,
- 0x10fd00001100,
+ 0x9850000098D,
+ 0x98F00000991,
+ 0x993000009A9,
+ 0x9AA000009B1,
+ 0x9B2000009B3,
+ 0x9B6000009BA,
+ 0x9BC000009C5,
+ 0x9C7000009C9,
+ 0x9CB000009CF,
+ 0x9D7000009D8,
+ 0x9E0000009E4,
+ 0x9E6000009F2,
+ 0x9FC000009FD,
+ 0x9FE000009FF,
+ 0xA0100000A04,
+ 0xA0500000A0B,
+ 0xA0F00000A11,
+ 0xA1300000A29,
+ 0xA2A00000A31,
+ 0xA3200000A33,
+ 0xA3500000A36,
+ 0xA3800000A3A,
+ 0xA3C00000A3D,
+ 0xA3E00000A43,
+ 0xA4700000A49,
+ 0xA4B00000A4E,
+ 0xA5100000A52,
+ 0xA5C00000A5D,
+ 0xA6600000A76,
+ 0xA8100000A84,
+ 0xA8500000A8E,
+ 0xA8F00000A92,
+ 0xA9300000AA9,
+ 0xAAA00000AB1,
+ 0xAB200000AB4,
+ 0xAB500000ABA,
+ 0xABC00000AC6,
+ 0xAC700000ACA,
+ 0xACB00000ACE,
+ 0xAD000000AD1,
+ 0xAE000000AE4,
+ 0xAE600000AF0,
+ 0xAF900000B00,
+ 0xB0100000B04,
+ 0xB0500000B0D,
+ 0xB0F00000B11,
+ 0xB1300000B29,
+ 0xB2A00000B31,
+ 0xB3200000B34,
+ 0xB3500000B3A,
+ 0xB3C00000B45,
+ 0xB4700000B49,
+ 0xB4B00000B4E,
+ 0xB5500000B58,
+ 0xB5F00000B64,
+ 0xB6600000B70,
+ 0xB7100000B72,
+ 0xB8200000B84,
+ 0xB8500000B8B,
+ 0xB8E00000B91,
+ 0xB9200000B96,
+ 0xB9900000B9B,
+ 0xB9C00000B9D,
+ 0xB9E00000BA0,
+ 0xBA300000BA5,
+ 0xBA800000BAB,
+ 0xBAE00000BBA,
+ 0xBBE00000BC3,
+ 0xBC600000BC9,
+ 0xBCA00000BCE,
+ 0xBD000000BD1,
+ 0xBD700000BD8,
+ 0xBE600000BF0,
+ 0xC0000000C0D,
+ 0xC0E00000C11,
+ 0xC1200000C29,
+ 0xC2A00000C3A,
+ 0xC3C00000C45,
+ 0xC4600000C49,
+ 0xC4A00000C4E,
+ 0xC5500000C57,
+ 0xC5800000C5B,
+ 0xC5D00000C5E,
+ 0xC6000000C64,
+ 0xC6600000C70,
+ 0xC8000000C84,
+ 0xC8500000C8D,
+ 0xC8E00000C91,
+ 0xC9200000CA9,
+ 0xCAA00000CB4,
+ 0xCB500000CBA,
+ 0xCBC00000CC5,
+ 0xCC600000CC9,
+ 0xCCA00000CCE,
+ 0xCD500000CD7,
+ 0xCDD00000CDF,
+ 0xCE000000CE4,
+ 0xCE600000CF0,
+ 0xCF100000CF4,
+ 0xD0000000D0D,
+ 0xD0E00000D11,
+ 0xD1200000D45,
+ 0xD4600000D49,
+ 0xD4A00000D4F,
+ 0xD5400000D58,
+ 0xD5F00000D64,
+ 0xD6600000D70,
+ 0xD7A00000D80,
+ 0xD8100000D84,
+ 0xD8500000D97,
+ 0xD9A00000DB2,
+ 0xDB300000DBC,
+ 0xDBD00000DBE,
+ 0xDC000000DC7,
+ 0xDCA00000DCB,
+ 0xDCF00000DD5,
+ 0xDD600000DD7,
+ 0xDD800000DE0,
+ 0xDE600000DF0,
+ 0xDF200000DF4,
+ 0xE0100000E33,
+ 0xE3400000E3B,
+ 0xE4000000E4F,
+ 0xE5000000E5A,
+ 0xE8100000E83,
+ 0xE8400000E85,
+ 0xE8600000E8B,
+ 0xE8C00000EA4,
+ 0xEA500000EA6,
+ 0xEA700000EB3,
+ 0xEB400000EBE,
+ 0xEC000000EC5,
+ 0xEC600000EC7,
+ 0xEC800000ECF,
+ 0xED000000EDA,
+ 0xEDE00000EE0,
+ 0xF0000000F01,
+ 0xF0B00000F0C,
+ 0xF1800000F1A,
+ 0xF2000000F2A,
+ 0xF3500000F36,
+ 0xF3700000F38,
+ 0xF3900000F3A,
+ 0xF3E00000F43,
+ 0xF4400000F48,
+ 0xF4900000F4D,
+ 0xF4E00000F52,
+ 0xF5300000F57,
+ 0xF5800000F5C,
+ 0xF5D00000F69,
+ 0xF6A00000F6D,
+ 0xF7100000F73,
+ 0xF7400000F75,
+ 0xF7A00000F81,
+ 0xF8200000F85,
+ 0xF8600000F93,
+ 0xF9400000F98,
+ 0xF9900000F9D,
+ 0xF9E00000FA2,
+ 0xFA300000FA7,
+ 0xFA800000FAC,
+ 0xFAD00000FB9,
+ 0xFBA00000FBD,
+ 0xFC600000FC7,
+ 0x10000000104A,
+ 0x10500000109E,
+ 0x10D0000010FB,
+ 0x10FD00001100,
0x120000001249,
- 0x124a0000124e,
+ 0x124A0000124E,
0x125000001257,
0x125800001259,
- 0x125a0000125e,
+ 0x125A0000125E,
0x126000001289,
- 0x128a0000128e,
- 0x1290000012b1,
- 0x12b2000012b6,
- 0x12b8000012bf,
- 0x12c0000012c1,
- 0x12c2000012c6,
- 0x12c8000012d7,
- 0x12d800001311,
+ 0x128A0000128E,
+ 0x1290000012B1,
+ 0x12B2000012B6,
+ 0x12B8000012BF,
+ 0x12C0000012C1,
+ 0x12C2000012C6,
+ 0x12C8000012D7,
+ 0x12D800001311,
0x131200001316,
- 0x13180000135b,
- 0x135d00001360,
+ 0x13180000135B,
+ 0x135D00001360,
0x138000001390,
- 0x13a0000013f6,
- 0x14010000166d,
- 0x166f00001680,
- 0x16810000169b,
- 0x16a0000016eb,
- 0x16f1000016f9,
+ 0x13A0000013F6,
+ 0x14010000166D,
+ 0x166F00001680,
+ 0x16810000169B,
+ 0x16A0000016EB,
+ 0x16F1000016F9,
0x170000001716,
- 0x171f00001735,
+ 0x171F00001735,
0x174000001754,
- 0x17600000176d,
- 0x176e00001771,
+ 0x17600000176D,
+ 0x176E00001771,
0x177200001774,
- 0x1780000017b4,
- 0x17b6000017d4,
- 0x17d7000017d8,
- 0x17dc000017de,
- 0x17e0000017ea,
- 0x18100000181a,
+ 0x1780000017B4,
+ 0x17B6000017D4,
+ 0x17D7000017D8,
+ 0x17DC000017DE,
+ 0x17E0000017EA,
+ 0x18100000181A,
0x182000001879,
- 0x1880000018ab,
- 0x18b0000018f6,
- 0x19000000191f,
- 0x19200000192c,
- 0x19300000193c,
- 0x19460000196e,
+ 0x1880000018AB,
+ 0x18B0000018F6,
+ 0x19000000191F,
+ 0x19200000192C,
+ 0x19300000193C,
+ 0x19460000196E,
0x197000001975,
- 0x1980000019ac,
- 0x19b0000019ca,
- 0x19d0000019da,
- 0x1a0000001a1c,
- 0x1a2000001a5f,
- 0x1a6000001a7d,
- 0x1a7f00001a8a,
- 0x1a9000001a9a,
- 0x1aa700001aa8,
- 0x1ab000001abe,
- 0x1abf00001acf,
- 0x1b0000001b4d,
- 0x1b5000001b5a,
- 0x1b6b00001b74,
- 0x1b8000001bf4,
- 0x1c0000001c38,
- 0x1c4000001c4a,
- 0x1c4d00001c7e,
- 0x1cd000001cd3,
- 0x1cd400001cfb,
- 0x1d0000001d2c,
- 0x1d2f00001d30,
- 0x1d3b00001d3c,
- 0x1d4e00001d4f,
- 0x1d6b00001d78,
- 0x1d7900001d9b,
- 0x1dc000001e00,
- 0x1e0100001e02,
- 0x1e0300001e04,
- 0x1e0500001e06,
- 0x1e0700001e08,
- 0x1e0900001e0a,
- 0x1e0b00001e0c,
- 0x1e0d00001e0e,
- 0x1e0f00001e10,
- 0x1e1100001e12,
- 0x1e1300001e14,
- 0x1e1500001e16,
- 0x1e1700001e18,
- 0x1e1900001e1a,
- 0x1e1b00001e1c,
- 0x1e1d00001e1e,
- 0x1e1f00001e20,
- 0x1e2100001e22,
- 0x1e2300001e24,
- 0x1e2500001e26,
- 0x1e2700001e28,
- 0x1e2900001e2a,
- 0x1e2b00001e2c,
- 0x1e2d00001e2e,
- 0x1e2f00001e30,
- 0x1e3100001e32,
- 0x1e3300001e34,
- 0x1e3500001e36,
- 0x1e3700001e38,
- 0x1e3900001e3a,
- 0x1e3b00001e3c,
- 0x1e3d00001e3e,
- 0x1e3f00001e40,
- 0x1e4100001e42,
- 0x1e4300001e44,
- 0x1e4500001e46,
- 0x1e4700001e48,
- 0x1e4900001e4a,
- 0x1e4b00001e4c,
- 0x1e4d00001e4e,
- 0x1e4f00001e50,
- 0x1e5100001e52,
- 0x1e5300001e54,
- 0x1e5500001e56,
- 0x1e5700001e58,
- 0x1e5900001e5a,
- 0x1e5b00001e5c,
- 0x1e5d00001e5e,
- 0x1e5f00001e60,
- 0x1e6100001e62,
- 0x1e6300001e64,
- 0x1e6500001e66,
- 0x1e6700001e68,
- 0x1e6900001e6a,
- 0x1e6b00001e6c,
- 0x1e6d00001e6e,
- 0x1e6f00001e70,
- 0x1e7100001e72,
- 0x1e7300001e74,
- 0x1e7500001e76,
- 0x1e7700001e78,
- 0x1e7900001e7a,
- 0x1e7b00001e7c,
- 0x1e7d00001e7e,
- 0x1e7f00001e80,
- 0x1e8100001e82,
- 0x1e8300001e84,
- 0x1e8500001e86,
- 0x1e8700001e88,
- 0x1e8900001e8a,
- 0x1e8b00001e8c,
- 0x1e8d00001e8e,
- 0x1e8f00001e90,
- 0x1e9100001e92,
- 0x1e9300001e94,
- 0x1e9500001e9a,
- 0x1e9c00001e9e,
- 0x1e9f00001ea0,
- 0x1ea100001ea2,
- 0x1ea300001ea4,
- 0x1ea500001ea6,
- 0x1ea700001ea8,
- 0x1ea900001eaa,
- 0x1eab00001eac,
- 0x1ead00001eae,
- 0x1eaf00001eb0,
- 0x1eb100001eb2,
- 0x1eb300001eb4,
- 0x1eb500001eb6,
- 0x1eb700001eb8,
- 0x1eb900001eba,
- 0x1ebb00001ebc,
- 0x1ebd00001ebe,
- 0x1ebf00001ec0,
- 0x1ec100001ec2,
- 0x1ec300001ec4,
- 0x1ec500001ec6,
- 0x1ec700001ec8,
- 0x1ec900001eca,
- 0x1ecb00001ecc,
- 0x1ecd00001ece,
- 0x1ecf00001ed0,
- 0x1ed100001ed2,
- 0x1ed300001ed4,
- 0x1ed500001ed6,
- 0x1ed700001ed8,
- 0x1ed900001eda,
- 0x1edb00001edc,
- 0x1edd00001ede,
- 0x1edf00001ee0,
- 0x1ee100001ee2,
- 0x1ee300001ee4,
- 0x1ee500001ee6,
- 0x1ee700001ee8,
- 0x1ee900001eea,
- 0x1eeb00001eec,
- 0x1eed00001eee,
- 0x1eef00001ef0,
- 0x1ef100001ef2,
- 0x1ef300001ef4,
- 0x1ef500001ef6,
- 0x1ef700001ef8,
- 0x1ef900001efa,
- 0x1efb00001efc,
- 0x1efd00001efe,
- 0x1eff00001f08,
- 0x1f1000001f16,
- 0x1f2000001f28,
- 0x1f3000001f38,
- 0x1f4000001f46,
- 0x1f5000001f58,
- 0x1f6000001f68,
- 0x1f7000001f71,
- 0x1f7200001f73,
- 0x1f7400001f75,
- 0x1f7600001f77,
- 0x1f7800001f79,
- 0x1f7a00001f7b,
- 0x1f7c00001f7d,
- 0x1fb000001fb2,
- 0x1fb600001fb7,
- 0x1fc600001fc7,
- 0x1fd000001fd3,
- 0x1fd600001fd8,
- 0x1fe000001fe3,
- 0x1fe400001fe8,
- 0x1ff600001ff7,
- 0x214e0000214f,
+ 0x1980000019AC,
+ 0x19B0000019CA,
+ 0x19D0000019DA,
+ 0x1A0000001A1C,
+ 0x1A2000001A5F,
+ 0x1A6000001A7D,
+ 0x1A7F00001A8A,
+ 0x1A9000001A9A,
+ 0x1AA700001AA8,
+ 0x1AB000001ABE,
+ 0x1ABF00001ACF,
+ 0x1B0000001B4D,
+ 0x1B5000001B5A,
+ 0x1B6B00001B74,
+ 0x1B8000001BF4,
+ 0x1C0000001C38,
+ 0x1C4000001C4A,
+ 0x1C4D00001C7E,
+ 0x1CD000001CD3,
+ 0x1CD400001CFB,
+ 0x1D0000001D2C,
+ 0x1D2F00001D30,
+ 0x1D3B00001D3C,
+ 0x1D4E00001D4F,
+ 0x1D6B00001D78,
+ 0x1D7900001D9B,
+ 0x1DC000001E00,
+ 0x1E0100001E02,
+ 0x1E0300001E04,
+ 0x1E0500001E06,
+ 0x1E0700001E08,
+ 0x1E0900001E0A,
+ 0x1E0B00001E0C,
+ 0x1E0D00001E0E,
+ 0x1E0F00001E10,
+ 0x1E1100001E12,
+ 0x1E1300001E14,
+ 0x1E1500001E16,
+ 0x1E1700001E18,
+ 0x1E1900001E1A,
+ 0x1E1B00001E1C,
+ 0x1E1D00001E1E,
+ 0x1E1F00001E20,
+ 0x1E2100001E22,
+ 0x1E2300001E24,
+ 0x1E2500001E26,
+ 0x1E2700001E28,
+ 0x1E2900001E2A,
+ 0x1E2B00001E2C,
+ 0x1E2D00001E2E,
+ 0x1E2F00001E30,
+ 0x1E3100001E32,
+ 0x1E3300001E34,
+ 0x1E3500001E36,
+ 0x1E3700001E38,
+ 0x1E3900001E3A,
+ 0x1E3B00001E3C,
+ 0x1E3D00001E3E,
+ 0x1E3F00001E40,
+ 0x1E4100001E42,
+ 0x1E4300001E44,
+ 0x1E4500001E46,
+ 0x1E4700001E48,
+ 0x1E4900001E4A,
+ 0x1E4B00001E4C,
+ 0x1E4D00001E4E,
+ 0x1E4F00001E50,
+ 0x1E5100001E52,
+ 0x1E5300001E54,
+ 0x1E5500001E56,
+ 0x1E5700001E58,
+ 0x1E5900001E5A,
+ 0x1E5B00001E5C,
+ 0x1E5D00001E5E,
+ 0x1E5F00001E60,
+ 0x1E6100001E62,
+ 0x1E6300001E64,
+ 0x1E6500001E66,
+ 0x1E6700001E68,
+ 0x1E6900001E6A,
+ 0x1E6B00001E6C,
+ 0x1E6D00001E6E,
+ 0x1E6F00001E70,
+ 0x1E7100001E72,
+ 0x1E7300001E74,
+ 0x1E7500001E76,
+ 0x1E7700001E78,
+ 0x1E7900001E7A,
+ 0x1E7B00001E7C,
+ 0x1E7D00001E7E,
+ 0x1E7F00001E80,
+ 0x1E8100001E82,
+ 0x1E8300001E84,
+ 0x1E8500001E86,
+ 0x1E8700001E88,
+ 0x1E8900001E8A,
+ 0x1E8B00001E8C,
+ 0x1E8D00001E8E,
+ 0x1E8F00001E90,
+ 0x1E9100001E92,
+ 0x1E9300001E94,
+ 0x1E9500001E9A,
+ 0x1E9C00001E9E,
+ 0x1E9F00001EA0,
+ 0x1EA100001EA2,
+ 0x1EA300001EA4,
+ 0x1EA500001EA6,
+ 0x1EA700001EA8,
+ 0x1EA900001EAA,
+ 0x1EAB00001EAC,
+ 0x1EAD00001EAE,
+ 0x1EAF00001EB0,
+ 0x1EB100001EB2,
+ 0x1EB300001EB4,
+ 0x1EB500001EB6,
+ 0x1EB700001EB8,
+ 0x1EB900001EBA,
+ 0x1EBB00001EBC,
+ 0x1EBD00001EBE,
+ 0x1EBF00001EC0,
+ 0x1EC100001EC2,
+ 0x1EC300001EC4,
+ 0x1EC500001EC6,
+ 0x1EC700001EC8,
+ 0x1EC900001ECA,
+ 0x1ECB00001ECC,
+ 0x1ECD00001ECE,
+ 0x1ECF00001ED0,
+ 0x1ED100001ED2,
+ 0x1ED300001ED4,
+ 0x1ED500001ED6,
+ 0x1ED700001ED8,
+ 0x1ED900001EDA,
+ 0x1EDB00001EDC,
+ 0x1EDD00001EDE,
+ 0x1EDF00001EE0,
+ 0x1EE100001EE2,
+ 0x1EE300001EE4,
+ 0x1EE500001EE6,
+ 0x1EE700001EE8,
+ 0x1EE900001EEA,
+ 0x1EEB00001EEC,
+ 0x1EED00001EEE,
+ 0x1EEF00001EF0,
+ 0x1EF100001EF2,
+ 0x1EF300001EF4,
+ 0x1EF500001EF6,
+ 0x1EF700001EF8,
+ 0x1EF900001EFA,
+ 0x1EFB00001EFC,
+ 0x1EFD00001EFE,
+ 0x1EFF00001F08,
+ 0x1F1000001F16,
+ 0x1F2000001F28,
+ 0x1F3000001F38,
+ 0x1F4000001F46,
+ 0x1F5000001F58,
+ 0x1F6000001F68,
+ 0x1F7000001F71,
+ 0x1F7200001F73,
+ 0x1F7400001F75,
+ 0x1F7600001F77,
+ 0x1F7800001F79,
+ 0x1F7A00001F7B,
+ 0x1F7C00001F7D,
+ 0x1FB000001FB2,
+ 0x1FB600001FB7,
+ 0x1FC600001FC7,
+ 0x1FD000001FD3,
+ 0x1FD600001FD8,
+ 0x1FE000001FE3,
+ 0x1FE400001FE8,
+ 0x1FF600001FF7,
+ 0x214E0000214F,
0x218400002185,
- 0x2c3000002c60,
- 0x2c6100002c62,
- 0x2c6500002c67,
- 0x2c6800002c69,
- 0x2c6a00002c6b,
- 0x2c6c00002c6d,
- 0x2c7100002c72,
- 0x2c7300002c75,
- 0x2c7600002c7c,
- 0x2c8100002c82,
- 0x2c8300002c84,
- 0x2c8500002c86,
- 0x2c8700002c88,
- 0x2c8900002c8a,
- 0x2c8b00002c8c,
- 0x2c8d00002c8e,
- 0x2c8f00002c90,
- 0x2c9100002c92,
- 0x2c9300002c94,
- 0x2c9500002c96,
- 0x2c9700002c98,
- 0x2c9900002c9a,
- 0x2c9b00002c9c,
- 0x2c9d00002c9e,
- 0x2c9f00002ca0,
- 0x2ca100002ca2,
- 0x2ca300002ca4,
- 0x2ca500002ca6,
- 0x2ca700002ca8,
- 0x2ca900002caa,
- 0x2cab00002cac,
- 0x2cad00002cae,
- 0x2caf00002cb0,
- 0x2cb100002cb2,
- 0x2cb300002cb4,
- 0x2cb500002cb6,
- 0x2cb700002cb8,
- 0x2cb900002cba,
- 0x2cbb00002cbc,
- 0x2cbd00002cbe,
- 0x2cbf00002cc0,
- 0x2cc100002cc2,
- 0x2cc300002cc4,
- 0x2cc500002cc6,
- 0x2cc700002cc8,
- 0x2cc900002cca,
- 0x2ccb00002ccc,
- 0x2ccd00002cce,
- 0x2ccf00002cd0,
- 0x2cd100002cd2,
- 0x2cd300002cd4,
- 0x2cd500002cd6,
- 0x2cd700002cd8,
- 0x2cd900002cda,
- 0x2cdb00002cdc,
- 0x2cdd00002cde,
- 0x2cdf00002ce0,
- 0x2ce100002ce2,
- 0x2ce300002ce5,
- 0x2cec00002ced,
- 0x2cee00002cf2,
- 0x2cf300002cf4,
- 0x2d0000002d26,
- 0x2d2700002d28,
- 0x2d2d00002d2e,
- 0x2d3000002d68,
- 0x2d7f00002d97,
- 0x2da000002da7,
- 0x2da800002daf,
- 0x2db000002db7,
- 0x2db800002dbf,
- 0x2dc000002dc7,
- 0x2dc800002dcf,
- 0x2dd000002dd7,
- 0x2dd800002ddf,
- 0x2de000002e00,
- 0x2e2f00002e30,
+ 0x2C3000002C60,
+ 0x2C6100002C62,
+ 0x2C6500002C67,
+ 0x2C6800002C69,
+ 0x2C6A00002C6B,
+ 0x2C6C00002C6D,
+ 0x2C7100002C72,
+ 0x2C7300002C75,
+ 0x2C7600002C7C,
+ 0x2C8100002C82,
+ 0x2C8300002C84,
+ 0x2C8500002C86,
+ 0x2C8700002C88,
+ 0x2C8900002C8A,
+ 0x2C8B00002C8C,
+ 0x2C8D00002C8E,
+ 0x2C8F00002C90,
+ 0x2C9100002C92,
+ 0x2C9300002C94,
+ 0x2C9500002C96,
+ 0x2C9700002C98,
+ 0x2C9900002C9A,
+ 0x2C9B00002C9C,
+ 0x2C9D00002C9E,
+ 0x2C9F00002CA0,
+ 0x2CA100002CA2,
+ 0x2CA300002CA4,
+ 0x2CA500002CA6,
+ 0x2CA700002CA8,
+ 0x2CA900002CAA,
+ 0x2CAB00002CAC,
+ 0x2CAD00002CAE,
+ 0x2CAF00002CB0,
+ 0x2CB100002CB2,
+ 0x2CB300002CB4,
+ 0x2CB500002CB6,
+ 0x2CB700002CB8,
+ 0x2CB900002CBA,
+ 0x2CBB00002CBC,
+ 0x2CBD00002CBE,
+ 0x2CBF00002CC0,
+ 0x2CC100002CC2,
+ 0x2CC300002CC4,
+ 0x2CC500002CC6,
+ 0x2CC700002CC8,
+ 0x2CC900002CCA,
+ 0x2CCB00002CCC,
+ 0x2CCD00002CCE,
+ 0x2CCF00002CD0,
+ 0x2CD100002CD2,
+ 0x2CD300002CD4,
+ 0x2CD500002CD6,
+ 0x2CD700002CD8,
+ 0x2CD900002CDA,
+ 0x2CDB00002CDC,
+ 0x2CDD00002CDE,
+ 0x2CDF00002CE0,
+ 0x2CE100002CE2,
+ 0x2CE300002CE5,
+ 0x2CEC00002CED,
+ 0x2CEE00002CF2,
+ 0x2CF300002CF4,
+ 0x2D0000002D26,
+ 0x2D2700002D28,
+ 0x2D2D00002D2E,
+ 0x2D3000002D68,
+ 0x2D7F00002D97,
+ 0x2DA000002DA7,
+ 0x2DA800002DAF,
+ 0x2DB000002DB7,
+ 0x2DB800002DBF,
+ 0x2DC000002DC7,
+ 0x2DC800002DCF,
+ 0x2DD000002DD7,
+ 0x2DD800002DDF,
+ 0x2DE000002E00,
+ 0x2E2F00002E30,
0x300500003008,
- 0x302a0000302e,
- 0x303c0000303d,
+ 0x302A0000302E,
+ 0x303C0000303D,
0x304100003097,
- 0x30990000309b,
- 0x309d0000309f,
- 0x30a1000030fb,
- 0x30fc000030ff,
+ 0x30990000309B,
+ 0x309D0000309F,
+ 0x30A1000030FB,
+ 0x30FC000030FF,
0x310500003130,
- 0x31a0000031c0,
- 0x31f000003200,
- 0x340000004dc0,
- 0x4e000000a48d,
- 0xa4d00000a4fe,
- 0xa5000000a60d,
- 0xa6100000a62c,
- 0xa6410000a642,
- 0xa6430000a644,
- 0xa6450000a646,
- 0xa6470000a648,
- 0xa6490000a64a,
- 0xa64b0000a64c,
- 0xa64d0000a64e,
- 0xa64f0000a650,
- 0xa6510000a652,
- 0xa6530000a654,
- 0xa6550000a656,
- 0xa6570000a658,
- 0xa6590000a65a,
- 0xa65b0000a65c,
- 0xa65d0000a65e,
- 0xa65f0000a660,
- 0xa6610000a662,
- 0xa6630000a664,
- 0xa6650000a666,
- 0xa6670000a668,
- 0xa6690000a66a,
- 0xa66b0000a66c,
- 0xa66d0000a670,
- 0xa6740000a67e,
- 0xa67f0000a680,
- 0xa6810000a682,
- 0xa6830000a684,
- 0xa6850000a686,
- 0xa6870000a688,
- 0xa6890000a68a,
- 0xa68b0000a68c,
- 0xa68d0000a68e,
- 0xa68f0000a690,
- 0xa6910000a692,
- 0xa6930000a694,
- 0xa6950000a696,
- 0xa6970000a698,
- 0xa6990000a69a,
- 0xa69b0000a69c,
- 0xa69e0000a6e6,
- 0xa6f00000a6f2,
- 0xa7170000a720,
- 0xa7230000a724,
- 0xa7250000a726,
- 0xa7270000a728,
- 0xa7290000a72a,
- 0xa72b0000a72c,
- 0xa72d0000a72e,
- 0xa72f0000a732,
- 0xa7330000a734,
- 0xa7350000a736,
- 0xa7370000a738,
- 0xa7390000a73a,
- 0xa73b0000a73c,
- 0xa73d0000a73e,
- 0xa73f0000a740,
- 0xa7410000a742,
- 0xa7430000a744,
- 0xa7450000a746,
- 0xa7470000a748,
- 0xa7490000a74a,
- 0xa74b0000a74c,
- 0xa74d0000a74e,
- 0xa74f0000a750,
- 0xa7510000a752,
- 0xa7530000a754,
- 0xa7550000a756,
- 0xa7570000a758,
- 0xa7590000a75a,
- 0xa75b0000a75c,
- 0xa75d0000a75e,
- 0xa75f0000a760,
- 0xa7610000a762,
- 0xa7630000a764,
- 0xa7650000a766,
- 0xa7670000a768,
- 0xa7690000a76a,
- 0xa76b0000a76c,
- 0xa76d0000a76e,
- 0xa76f0000a770,
- 0xa7710000a779,
- 0xa77a0000a77b,
- 0xa77c0000a77d,
- 0xa77f0000a780,
- 0xa7810000a782,
- 0xa7830000a784,
- 0xa7850000a786,
- 0xa7870000a789,
- 0xa78c0000a78d,
- 0xa78e0000a790,
- 0xa7910000a792,
- 0xa7930000a796,
- 0xa7970000a798,
- 0xa7990000a79a,
- 0xa79b0000a79c,
- 0xa79d0000a79e,
- 0xa79f0000a7a0,
- 0xa7a10000a7a2,
- 0xa7a30000a7a4,
- 0xa7a50000a7a6,
- 0xa7a70000a7a8,
- 0xa7a90000a7aa,
- 0xa7af0000a7b0,
- 0xa7b50000a7b6,
- 0xa7b70000a7b8,
- 0xa7b90000a7ba,
- 0xa7bb0000a7bc,
- 0xa7bd0000a7be,
- 0xa7bf0000a7c0,
- 0xa7c10000a7c2,
- 0xa7c30000a7c4,
- 0xa7c80000a7c9,
- 0xa7ca0000a7cb,
- 0xa7d10000a7d2,
- 0xa7d30000a7d4,
- 0xa7d50000a7d6,
- 0xa7d70000a7d8,
- 0xa7d90000a7da,
- 0xa7f60000a7f8,
- 0xa7fa0000a828,
- 0xa82c0000a82d,
- 0xa8400000a874,
- 0xa8800000a8c6,
- 0xa8d00000a8da,
- 0xa8e00000a8f8,
- 0xa8fb0000a8fc,
- 0xa8fd0000a92e,
- 0xa9300000a954,
- 0xa9800000a9c1,
- 0xa9cf0000a9da,
- 0xa9e00000a9ff,
- 0xaa000000aa37,
- 0xaa400000aa4e,
- 0xaa500000aa5a,
- 0xaa600000aa77,
- 0xaa7a0000aac3,
- 0xaadb0000aade,
- 0xaae00000aaf0,
- 0xaaf20000aaf7,
- 0xab010000ab07,
- 0xab090000ab0f,
- 0xab110000ab17,
- 0xab200000ab27,
- 0xab280000ab2f,
- 0xab300000ab5b,
- 0xab600000ab69,
- 0xabc00000abeb,
- 0xabec0000abee,
- 0xabf00000abfa,
- 0xac000000d7a4,
- 0xfa0e0000fa10,
- 0xfa110000fa12,
- 0xfa130000fa15,
- 0xfa1f0000fa20,
- 0xfa210000fa22,
- 0xfa230000fa25,
- 0xfa270000fa2a,
- 0xfb1e0000fb1f,
- 0xfe200000fe30,
- 0xfe730000fe74,
- 0x100000001000c,
- 0x1000d00010027,
- 0x100280001003b,
- 0x1003c0001003e,
- 0x1003f0001004e,
- 0x100500001005e,
- 0x10080000100fb,
- 0x101fd000101fe,
- 0x102800001029d,
- 0x102a0000102d1,
- 0x102e0000102e1,
+ 0x31A0000031C0,
+ 0x31F000003200,
+ 0x340000004DC0,
+ 0x4E000000A48D,
+ 0xA4D00000A4FE,
+ 0xA5000000A60D,
+ 0xA6100000A62C,
+ 0xA6410000A642,
+ 0xA6430000A644,
+ 0xA6450000A646,
+ 0xA6470000A648,
+ 0xA6490000A64A,
+ 0xA64B0000A64C,
+ 0xA64D0000A64E,
+ 0xA64F0000A650,
+ 0xA6510000A652,
+ 0xA6530000A654,
+ 0xA6550000A656,
+ 0xA6570000A658,
+ 0xA6590000A65A,
+ 0xA65B0000A65C,
+ 0xA65D0000A65E,
+ 0xA65F0000A660,
+ 0xA6610000A662,
+ 0xA6630000A664,
+ 0xA6650000A666,
+ 0xA6670000A668,
+ 0xA6690000A66A,
+ 0xA66B0000A66C,
+ 0xA66D0000A670,
+ 0xA6740000A67E,
+ 0xA67F0000A680,
+ 0xA6810000A682,
+ 0xA6830000A684,
+ 0xA6850000A686,
+ 0xA6870000A688,
+ 0xA6890000A68A,
+ 0xA68B0000A68C,
+ 0xA68D0000A68E,
+ 0xA68F0000A690,
+ 0xA6910000A692,
+ 0xA6930000A694,
+ 0xA6950000A696,
+ 0xA6970000A698,
+ 0xA6990000A69A,
+ 0xA69B0000A69C,
+ 0xA69E0000A6E6,
+ 0xA6F00000A6F2,
+ 0xA7170000A720,
+ 0xA7230000A724,
+ 0xA7250000A726,
+ 0xA7270000A728,
+ 0xA7290000A72A,
+ 0xA72B0000A72C,
+ 0xA72D0000A72E,
+ 0xA72F0000A732,
+ 0xA7330000A734,
+ 0xA7350000A736,
+ 0xA7370000A738,
+ 0xA7390000A73A,
+ 0xA73B0000A73C,
+ 0xA73D0000A73E,
+ 0xA73F0000A740,
+ 0xA7410000A742,
+ 0xA7430000A744,
+ 0xA7450000A746,
+ 0xA7470000A748,
+ 0xA7490000A74A,
+ 0xA74B0000A74C,
+ 0xA74D0000A74E,
+ 0xA74F0000A750,
+ 0xA7510000A752,
+ 0xA7530000A754,
+ 0xA7550000A756,
+ 0xA7570000A758,
+ 0xA7590000A75A,
+ 0xA75B0000A75C,
+ 0xA75D0000A75E,
+ 0xA75F0000A760,
+ 0xA7610000A762,
+ 0xA7630000A764,
+ 0xA7650000A766,
+ 0xA7670000A768,
+ 0xA7690000A76A,
+ 0xA76B0000A76C,
+ 0xA76D0000A76E,
+ 0xA76F0000A770,
+ 0xA7710000A779,
+ 0xA77A0000A77B,
+ 0xA77C0000A77D,
+ 0xA77F0000A780,
+ 0xA7810000A782,
+ 0xA7830000A784,
+ 0xA7850000A786,
+ 0xA7870000A789,
+ 0xA78C0000A78D,
+ 0xA78E0000A790,
+ 0xA7910000A792,
+ 0xA7930000A796,
+ 0xA7970000A798,
+ 0xA7990000A79A,
+ 0xA79B0000A79C,
+ 0xA79D0000A79E,
+ 0xA79F0000A7A0,
+ 0xA7A10000A7A2,
+ 0xA7A30000A7A4,
+ 0xA7A50000A7A6,
+ 0xA7A70000A7A8,
+ 0xA7A90000A7AA,
+ 0xA7AF0000A7B0,
+ 0xA7B50000A7B6,
+ 0xA7B70000A7B8,
+ 0xA7B90000A7BA,
+ 0xA7BB0000A7BC,
+ 0xA7BD0000A7BE,
+ 0xA7BF0000A7C0,
+ 0xA7C10000A7C2,
+ 0xA7C30000A7C4,
+ 0xA7C80000A7C9,
+ 0xA7CA0000A7CB,
+ 0xA7D10000A7D2,
+ 0xA7D30000A7D4,
+ 0xA7D50000A7D6,
+ 0xA7D70000A7D8,
+ 0xA7D90000A7DA,
+ 0xA7F60000A7F8,
+ 0xA7FA0000A828,
+ 0xA82C0000A82D,
+ 0xA8400000A874,
+ 0xA8800000A8C6,
+ 0xA8D00000A8DA,
+ 0xA8E00000A8F8,
+ 0xA8FB0000A8FC,
+ 0xA8FD0000A92E,
+ 0xA9300000A954,
+ 0xA9800000A9C1,
+ 0xA9CF0000A9DA,
+ 0xA9E00000A9FF,
+ 0xAA000000AA37,
+ 0xAA400000AA4E,
+ 0xAA500000AA5A,
+ 0xAA600000AA77,
+ 0xAA7A0000AAC3,
+ 0xAADB0000AADE,
+ 0xAAE00000AAF0,
+ 0xAAF20000AAF7,
+ 0xAB010000AB07,
+ 0xAB090000AB0F,
+ 0xAB110000AB17,
+ 0xAB200000AB27,
+ 0xAB280000AB2F,
+ 0xAB300000AB5B,
+ 0xAB600000AB69,
+ 0xABC00000ABEB,
+ 0xABEC0000ABEE,
+ 0xABF00000ABFA,
+ 0xAC000000D7A4,
+ 0xFA0E0000FA10,
+ 0xFA110000FA12,
+ 0xFA130000FA15,
+ 0xFA1F0000FA20,
+ 0xFA210000FA22,
+ 0xFA230000FA25,
+ 0xFA270000FA2A,
+ 0xFB1E0000FB1F,
+ 0xFE200000FE30,
+ 0xFE730000FE74,
+ 0x100000001000C,
+ 0x1000D00010027,
+ 0x100280001003B,
+ 0x1003C0001003E,
+ 0x1003F0001004E,
+ 0x100500001005E,
+ 0x10080000100FB,
+ 0x101FD000101FE,
+ 0x102800001029D,
+ 0x102A0000102D1,
+ 0x102E0000102E1,
0x1030000010320,
- 0x1032d00010341,
- 0x103420001034a,
- 0x103500001037b,
- 0x103800001039e,
- 0x103a0000103c4,
- 0x103c8000103d0,
- 0x104280001049e,
- 0x104a0000104aa,
- 0x104d8000104fc,
+ 0x1032D00010341,
+ 0x103420001034A,
+ 0x103500001037B,
+ 0x103800001039E,
+ 0x103A0000103C4,
+ 0x103C8000103D0,
+ 0x104280001049E,
+ 0x104A0000104AA,
+ 0x104D8000104FC,
0x1050000010528,
0x1053000010564,
- 0x10597000105a2,
- 0x105a3000105b2,
- 0x105b3000105ba,
- 0x105bb000105bd,
+ 0x10597000105A2,
+ 0x105A3000105B2,
+ 0x105B3000105BA,
+ 0x105BB000105BD,
0x1060000010737,
0x1074000010756,
0x1076000010768,
0x1078000010781,
0x1080000010806,
0x1080800010809,
- 0x1080a00010836,
+ 0x1080A00010836,
0x1083700010839,
- 0x1083c0001083d,
- 0x1083f00010856,
+ 0x1083C0001083D,
+ 0x1083F00010856,
0x1086000010877,
- 0x108800001089f,
- 0x108e0000108f3,
- 0x108f4000108f6,
+ 0x108800001089F,
+ 0x108E0000108F3,
+ 0x108F4000108F6,
0x1090000010916,
- 0x109200001093a,
- 0x10980000109b8,
- 0x109be000109c0,
- 0x10a0000010a04,
- 0x10a0500010a07,
- 0x10a0c00010a14,
- 0x10a1500010a18,
- 0x10a1900010a36,
- 0x10a3800010a3b,
- 0x10a3f00010a40,
- 0x10a6000010a7d,
- 0x10a8000010a9d,
- 0x10ac000010ac8,
- 0x10ac900010ae7,
- 0x10b0000010b36,
- 0x10b4000010b56,
- 0x10b6000010b73,
- 0x10b8000010b92,
- 0x10c0000010c49,
- 0x10cc000010cf3,
- 0x10d0000010d28,
- 0x10d3000010d3a,
- 0x10e8000010eaa,
- 0x10eab00010ead,
- 0x10eb000010eb2,
- 0x10efd00010f1d,
- 0x10f2700010f28,
- 0x10f3000010f51,
- 0x10f7000010f86,
- 0x10fb000010fc5,
- 0x10fe000010ff7,
+ 0x109200001093A,
+ 0x10980000109B8,
+ 0x109BE000109C0,
+ 0x10A0000010A04,
+ 0x10A0500010A07,
+ 0x10A0C00010A14,
+ 0x10A1500010A18,
+ 0x10A1900010A36,
+ 0x10A3800010A3B,
+ 0x10A3F00010A40,
+ 0x10A6000010A7D,
+ 0x10A8000010A9D,
+ 0x10AC000010AC8,
+ 0x10AC900010AE7,
+ 0x10B0000010B36,
+ 0x10B4000010B56,
+ 0x10B6000010B73,
+ 0x10B8000010B92,
+ 0x10C0000010C49,
+ 0x10CC000010CF3,
+ 0x10D0000010D28,
+ 0x10D3000010D3A,
+ 0x10E8000010EAA,
+ 0x10EAB00010EAD,
+ 0x10EB000010EB2,
+ 0x10EFD00010F1D,
+ 0x10F2700010F28,
+ 0x10F3000010F51,
+ 0x10F7000010F86,
+ 0x10FB000010FC5,
+ 0x10FE000010FF7,
0x1100000011047,
0x1106600011076,
- 0x1107f000110bb,
- 0x110c2000110c3,
- 0x110d0000110e9,
- 0x110f0000110fa,
+ 0x1107F000110BB,
+ 0x110C2000110C3,
+ 0x110D0000110E9,
+ 0x110F0000110FA,
0x1110000011135,
0x1113600011140,
0x1114400011148,
0x1115000011174,
0x1117600011177,
- 0x11180000111c5,
- 0x111c9000111cd,
- 0x111ce000111db,
- 0x111dc000111dd,
+ 0x11180000111C5,
+ 0x111C9000111CD,
+ 0x111CE000111DB,
+ 0x111DC000111DD,
0x1120000011212,
0x1121300011238,
- 0x1123e00011242,
+ 0x1123E00011242,
0x1128000011287,
0x1128800011289,
- 0x1128a0001128e,
- 0x1128f0001129e,
- 0x1129f000112a9,
- 0x112b0000112eb,
- 0x112f0000112fa,
+ 0x1128A0001128E,
+ 0x1128F0001129E,
+ 0x1129F000112A9,
+ 0x112B0000112EB,
+ 0x112F0000112FA,
0x1130000011304,
- 0x113050001130d,
- 0x1130f00011311,
+ 0x113050001130D,
+ 0x1130F00011311,
0x1131300011329,
- 0x1132a00011331,
+ 0x1132A00011331,
0x1133200011334,
- 0x113350001133a,
- 0x1133b00011345,
+ 0x113350001133A,
+ 0x1133B00011345,
0x1134700011349,
- 0x1134b0001134e,
+ 0x1134B0001134E,
0x1135000011351,
0x1135700011358,
- 0x1135d00011364,
- 0x113660001136d,
+ 0x1135D00011364,
+ 0x113660001136D,
0x1137000011375,
- 0x114000001144b,
- 0x114500001145a,
- 0x1145e00011462,
- 0x11480000114c6,
- 0x114c7000114c8,
- 0x114d0000114da,
- 0x11580000115b6,
- 0x115b8000115c1,
- 0x115d8000115de,
+ 0x114000001144B,
+ 0x114500001145A,
+ 0x1145E00011462,
+ 0x11480000114C6,
+ 0x114C7000114C8,
+ 0x114D0000114DA,
+ 0x11580000115B6,
+ 0x115B8000115C1,
+ 0x115D8000115DE,
0x1160000011641,
0x1164400011645,
- 0x116500001165a,
- 0x11680000116b9,
- 0x116c0000116ca,
- 0x117000001171b,
- 0x1171d0001172c,
- 0x117300001173a,
+ 0x116500001165A,
+ 0x11680000116B9,
+ 0x116C0000116CA,
+ 0x117000001171B,
+ 0x1171D0001172C,
+ 0x117300001173A,
0x1174000011747,
- 0x118000001183b,
- 0x118c0000118ea,
- 0x118ff00011907,
- 0x119090001190a,
- 0x1190c00011914,
+ 0x118000001183B,
+ 0x118C0000118EA,
+ 0x118FF00011907,
+ 0x119090001190A,
+ 0x1190C00011914,
0x1191500011917,
0x1191800011936,
0x1193700011939,
- 0x1193b00011944,
- 0x119500001195a,
- 0x119a0000119a8,
- 0x119aa000119d8,
- 0x119da000119e2,
- 0x119e3000119e5,
- 0x11a0000011a3f,
- 0x11a4700011a48,
- 0x11a5000011a9a,
- 0x11a9d00011a9e,
- 0x11ab000011af9,
- 0x11c0000011c09,
- 0x11c0a00011c37,
- 0x11c3800011c41,
- 0x11c5000011c5a,
- 0x11c7200011c90,
- 0x11c9200011ca8,
- 0x11ca900011cb7,
- 0x11d0000011d07,
- 0x11d0800011d0a,
- 0x11d0b00011d37,
- 0x11d3a00011d3b,
- 0x11d3c00011d3e,
- 0x11d3f00011d48,
- 0x11d5000011d5a,
- 0x11d6000011d66,
- 0x11d6700011d69,
- 0x11d6a00011d8f,
- 0x11d9000011d92,
- 0x11d9300011d99,
- 0x11da000011daa,
- 0x11ee000011ef7,
- 0x11f0000011f11,
- 0x11f1200011f3b,
- 0x11f3e00011f43,
- 0x11f5000011f5a,
- 0x11fb000011fb1,
- 0x120000001239a,
+ 0x1193B00011944,
+ 0x119500001195A,
+ 0x119A0000119A8,
+ 0x119AA000119D8,
+ 0x119DA000119E2,
+ 0x119E3000119E5,
+ 0x11A0000011A3F,
+ 0x11A4700011A48,
+ 0x11A5000011A9A,
+ 0x11A9D00011A9E,
+ 0x11AB000011AF9,
+ 0x11C0000011C09,
+ 0x11C0A00011C37,
+ 0x11C3800011C41,
+ 0x11C5000011C5A,
+ 0x11C7200011C90,
+ 0x11C9200011CA8,
+ 0x11CA900011CB7,
+ 0x11D0000011D07,
+ 0x11D0800011D0A,
+ 0x11D0B00011D37,
+ 0x11D3A00011D3B,
+ 0x11D3C00011D3E,
+ 0x11D3F00011D48,
+ 0x11D5000011D5A,
+ 0x11D6000011D66,
+ 0x11D6700011D69,
+ 0x11D6A00011D8F,
+ 0x11D9000011D92,
+ 0x11D9300011D99,
+ 0x11DA000011DAA,
+ 0x11EE000011EF7,
+ 0x11F0000011F11,
+ 0x11F1200011F3B,
+ 0x11F3E00011F43,
+ 0x11F5000011F5A,
+ 0x11FB000011FB1,
+ 0x120000001239A,
0x1248000012544,
- 0x12f9000012ff1,
+ 0x12F9000012FF1,
0x1300000013430,
0x1344000013456,
0x1440000014647,
- 0x1680000016a39,
- 0x16a4000016a5f,
- 0x16a6000016a6a,
- 0x16a7000016abf,
- 0x16ac000016aca,
- 0x16ad000016aee,
- 0x16af000016af5,
- 0x16b0000016b37,
- 0x16b4000016b44,
- 0x16b5000016b5a,
- 0x16b6300016b78,
- 0x16b7d00016b90,
- 0x16e6000016e80,
- 0x16f0000016f4b,
- 0x16f4f00016f88,
- 0x16f8f00016fa0,
- 0x16fe000016fe2,
- 0x16fe300016fe5,
- 0x16ff000016ff2,
- 0x17000000187f8,
- 0x1880000018cd6,
- 0x18d0000018d09,
- 0x1aff00001aff4,
- 0x1aff50001affc,
- 0x1affd0001afff,
- 0x1b0000001b123,
- 0x1b1320001b133,
- 0x1b1500001b153,
- 0x1b1550001b156,
- 0x1b1640001b168,
- 0x1b1700001b2fc,
- 0x1bc000001bc6b,
- 0x1bc700001bc7d,
- 0x1bc800001bc89,
- 0x1bc900001bc9a,
- 0x1bc9d0001bc9f,
- 0x1cf000001cf2e,
- 0x1cf300001cf47,
- 0x1da000001da37,
- 0x1da3b0001da6d,
- 0x1da750001da76,
- 0x1da840001da85,
- 0x1da9b0001daa0,
- 0x1daa10001dab0,
- 0x1df000001df1f,
- 0x1df250001df2b,
- 0x1e0000001e007,
- 0x1e0080001e019,
- 0x1e01b0001e022,
- 0x1e0230001e025,
- 0x1e0260001e02b,
- 0x1e08f0001e090,
- 0x1e1000001e12d,
- 0x1e1300001e13e,
- 0x1e1400001e14a,
- 0x1e14e0001e14f,
- 0x1e2900001e2af,
- 0x1e2c00001e2fa,
- 0x1e4d00001e4fa,
- 0x1e7e00001e7e7,
- 0x1e7e80001e7ec,
- 0x1e7ed0001e7ef,
- 0x1e7f00001e7ff,
- 0x1e8000001e8c5,
- 0x1e8d00001e8d7,
- 0x1e9220001e94c,
- 0x1e9500001e95a,
- 0x200000002a6e0,
- 0x2a7000002b73a,
- 0x2b7400002b81e,
- 0x2b8200002cea2,
- 0x2ceb00002ebe1,
- 0x2ebf00002ee5e,
- 0x300000003134b,
- 0x31350000323b0,
+ 0x1680000016A39,
+ 0x16A4000016A5F,
+ 0x16A6000016A6A,
+ 0x16A7000016ABF,
+ 0x16AC000016ACA,
+ 0x16AD000016AEE,
+ 0x16AF000016AF5,
+ 0x16B0000016B37,
+ 0x16B4000016B44,
+ 0x16B5000016B5A,
+ 0x16B6300016B78,
+ 0x16B7D00016B90,
+ 0x16E6000016E80,
+ 0x16F0000016F4B,
+ 0x16F4F00016F88,
+ 0x16F8F00016FA0,
+ 0x16FE000016FE2,
+ 0x16FE300016FE5,
+ 0x16FF000016FF2,
+ 0x17000000187F8,
+ 0x1880000018CD6,
+ 0x18D0000018D09,
+ 0x1AFF00001AFF4,
+ 0x1AFF50001AFFC,
+ 0x1AFFD0001AFFF,
+ 0x1B0000001B123,
+ 0x1B1320001B133,
+ 0x1B1500001B153,
+ 0x1B1550001B156,
+ 0x1B1640001B168,
+ 0x1B1700001B2FC,
+ 0x1BC000001BC6B,
+ 0x1BC700001BC7D,
+ 0x1BC800001BC89,
+ 0x1BC900001BC9A,
+ 0x1BC9D0001BC9F,
+ 0x1CF000001CF2E,
+ 0x1CF300001CF47,
+ 0x1DA000001DA37,
+ 0x1DA3B0001DA6D,
+ 0x1DA750001DA76,
+ 0x1DA840001DA85,
+ 0x1DA9B0001DAA0,
+ 0x1DAA10001DAB0,
+ 0x1DF000001DF1F,
+ 0x1DF250001DF2B,
+ 0x1E0000001E007,
+ 0x1E0080001E019,
+ 0x1E01B0001E022,
+ 0x1E0230001E025,
+ 0x1E0260001E02B,
+ 0x1E08F0001E090,
+ 0x1E1000001E12D,
+ 0x1E1300001E13E,
+ 0x1E1400001E14A,
+ 0x1E14E0001E14F,
+ 0x1E2900001E2AF,
+ 0x1E2C00001E2FA,
+ 0x1E4D00001E4FA,
+ 0x1E7E00001E7E7,
+ 0x1E7E80001E7EC,
+ 0x1E7ED0001E7EF,
+ 0x1E7F00001E7FF,
+ 0x1E8000001E8C5,
+ 0x1E8D00001E8D7,
+ 0x1E9220001E94C,
+ 0x1E9500001E95A,
+ 0x200000002A6E0,
+ 0x2A7000002B73A,
+ 0x2B7400002B81E,
+ 0x2B8200002CEA2,
+ 0x2CEB00002EBE1,
+ 0x2EBF00002EE5E,
+ 0x300000003134B,
+ 0x31350000323B0,
),
- 'CONTEXTJ': (
- 0x200c0000200e,
- ),
- 'CONTEXTO': (
- 0xb7000000b8,
+ "CONTEXTJ": (0x200C0000200E,),
+ "CONTEXTO": (
+ 0xB7000000B8,
0x37500000376,
- 0x5f3000005f5,
- 0x6600000066a,
- 0x6f0000006fa,
- 0x30fb000030fc,
+ 0x5F3000005F5,
+ 0x6600000066A,
+ 0x6F0000006FA,
+ 0x30FB000030FC,
),
}
diff --git a/lib/idna/intranges.py b/lib/idna/intranges.py
index 6a43b047..7bfaa8d8 100644
--- a/lib/idna/intranges.py
+++ b/lib/idna/intranges.py
@@ -8,6 +8,7 @@ in the original list?" in time O(log(# runs)).
import bisect
from typing import List, Tuple
+
def intranges_from_list(list_: List[int]) -> Tuple[int, ...]:
"""Represent a list of integers as a sequence of ranges:
((start_0, end_0), (start_1, end_1), ...), such that the original
@@ -20,18 +21,20 @@ def intranges_from_list(list_: List[int]) -> Tuple[int, ...]:
ranges = []
last_write = -1
for i in range(len(sorted_list)):
- if i+1 < len(sorted_list):
- if sorted_list[i] == sorted_list[i+1]-1:
+ if i + 1 < len(sorted_list):
+ if sorted_list[i] == sorted_list[i + 1] - 1:
continue
- current_range = sorted_list[last_write+1:i+1]
+ current_range = sorted_list[last_write + 1 : i + 1]
ranges.append(_encode_range(current_range[0], current_range[-1] + 1))
last_write = i
return tuple(ranges)
+
def _encode_range(start: int, end: int) -> int:
return (start << 32) | end
+
def _decode_range(r: int) -> Tuple[int, int]:
return (r >> 32), (r & ((1 << 32) - 1))
@@ -43,7 +46,7 @@ def intranges_contain(int_: int, ranges: Tuple[int, ...]) -> bool:
# we could be immediately ahead of a tuple (start, end)
# with start < int_ <= end
if pos > 0:
- left, right = _decode_range(ranges[pos-1])
+ left, right = _decode_range(ranges[pos - 1])
if left <= int_ < right:
return True
# or we could be immediately behind a tuple (int_, end)
diff --git a/lib/idna/package_data.py b/lib/idna/package_data.py
index ed811133..514ff7e2 100644
--- a/lib/idna/package_data.py
+++ b/lib/idna/package_data.py
@@ -1,2 +1 @@
-__version__ = '3.7'
-
+__version__ = "3.10"
diff --git a/lib/idna/uts46data.py b/lib/idna/uts46data.py
index 6a1eddbf..eb894327 100644
--- a/lib/idna/uts46data.py
+++ b/lib/idna/uts46data.py
@@ -3,8515 +3,8598 @@
from typing import List, Tuple, Union
-
"""IDNA Mapping Table from UTS46."""
-__version__ = '15.1.0'
+__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'),
+ (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', 'ç'),
+ (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'),
+ (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', 'ɠ'),
+ (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', 'ȍ'),
+ (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'),
+ (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', 'ђ'),
+ (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'),
+ (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', 'ԃ'),
+ (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'),
+ (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'),
+ (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'),
+ (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'),
+ (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'),
+ (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', 'в'),
+ (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', 'ɔ'),
+ (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'),
+ (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'),
+ (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', 'ự'),
+ (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', 'ἇι'),
+ (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'),
+ (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'),
+ (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'),
+ (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'),
+ (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', 'ⱜ'),
+ (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', 'ⳇ'),
+ (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', '卩'),
+ (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', '而'),
+ (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'),
+ (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', 'ᆅ'),
+ (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'),
+ (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'),
+ (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', 'グラムトン'),
+ (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', '大正'),
+ (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日'),
+ (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'),
+ (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'),
+ (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'),
+ (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', 'Ꮮ'),
+ (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', '雷'),
+ (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', '玲'),
+ (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', '晴'),
+ (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', '塚'),
+ (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'),
+ (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', 'ى'),
+ (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', 'يي'),
+ (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', 'فج'),
+ (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', 'صي'),
+ (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', 'شحي'),
+ (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', '*'),
+ (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', '>'),
+ (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', 'ツ'),
+ (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', '■'),
+ (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', '𐓡'),
+ (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', 'ɗ'),
+ (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'),
+ (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'),
+ (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', '𑣊'),
+ (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'),
+ (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'),
+ (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'),
+ (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'),
+ (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'),
+ (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'),
+ (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'),
+ (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'),
+ (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'),
+ (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', 'η'),
+ (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', 'ω'),
+ (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', 'κ'),
+ (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', 'ж'),
+ (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', '𞤯'),
+ (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', 'س'),
+ (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', 'ذ'),
+ (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'),
+ (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'),
+ (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', '咢'),
+ (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', '慎'),
+ (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', '滇'),
+ (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', '𦉇'),
+ (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', '起'),
+ (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'),
+ (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()
diff --git a/lib/importlib_metadata/__init__.py b/lib/importlib_metadata/__init__.py
index 2c71d33c..46a14e64 100644
--- a/lib/importlib_metadata/__init__.py
+++ b/lib/importlib_metadata/__init__.py
@@ -1,24 +1,34 @@
+"""
+APIs exposing metadata from third-party Python packages.
+
+This codebase is shared between importlib.metadata in the stdlib
+and importlib_metadata in PyPI. See
+https://github.com/python/importlib_metadata/wiki/Development-Methodology
+for more detail.
+"""
+
from __future__ import annotations
-import os
-import re
import abc
-import sys
-import json
-import zipp
+import collections
import email
-import types
-import inspect
-import pathlib
-import operator
-import textwrap
import functools
import itertools
+import operator
+import os
+import pathlib
import posixpath
-import collections
+import re
+import sys
+import textwrap
+import types
+from contextlib import suppress
+from importlib import import_module
+from importlib.abc import MetaPathFinder
+from itertools import starmap
+from typing import Any, Iterable, List, Mapping, Match, Optional, Set, cast
from . import _meta
-from .compat import py39, py311
from ._collections import FreezableDefaultDict, Pair
from ._compat import (
NullFinder,
@@ -27,12 +37,7 @@ from ._compat import (
from ._functools import method_cache, pass_none
from ._itertools import always_iterable, bucket, unique_everseen
from ._meta import PackageMetadata, SimplePath
-
-from contextlib import suppress
-from importlib import import_module
-from importlib.abc import MetaPathFinder
-from itertools import starmap
-from typing import Any, Iterable, List, Mapping, Match, Optional, Set, cast
+from .compat import py39, py311
__all__ = [
'Distribution',
@@ -58,7 +63,7 @@ class PackageNotFoundError(ModuleNotFoundError):
return f"No package metadata was found for {self.name}"
@property
- def name(self) -> str: # type: ignore[override]
+ def name(self) -> str: # type: ignore[override] # make readonly
(name,) = self.args
return name
@@ -227,9 +232,26 @@ class EntryPoint:
>>> ep.matches(attr='bong')
True
"""
+ self._disallow_dist(params)
attrs = (getattr(self, param) for param in params)
return all(map(operator.eq, params.values(), attrs))
+ @staticmethod
+ def _disallow_dist(params):
+ """
+ Querying by dist is not allowed (dist objects are not comparable).
+ >>> EntryPoint(name='fan', value='fav', group='fag').matches(dist='foo')
+ Traceback (most recent call last):
+ ...
+ ValueError: "dist" is not suitable for matching...
+ """
+ if "dist" in params:
+ raise ValueError(
+ '"dist" is not suitable for matching. '
+ "Instead, use Distribution.entry_points.select() on a "
+ "located distribution."
+ )
+
def _key(self):
return self.name, self.value, self.group
@@ -259,7 +281,7 @@ class EntryPoints(tuple):
__slots__ = ()
- def __getitem__(self, name: str) -> EntryPoint: # type: ignore[override]
+ def __getitem__(self, name: str) -> EntryPoint: # type: ignore[override] # Work with str instead of int
"""
Get the EntryPoint in self matching name.
"""
@@ -315,7 +337,7 @@ class PackagePath(pathlib.PurePosixPath):
size: int
dist: Distribution
- def read_text(self, encoding: str = 'utf-8') -> str: # type: ignore[override]
+ def read_text(self, encoding: str = 'utf-8') -> str:
return self.locate().read_text(encoding=encoding)
def read_binary(self) -> bytes:
@@ -373,6 +395,17 @@ class Distribution(metaclass=abc.ABCMeta):
"""
Given a path to a file in this distribution, return a SimplePath
to it.
+
+ This method is used by callers of ``Distribution.files()`` to
+ locate files within the distribution. If it's possible for a
+ Distribution to represent files in the distribution as
+ ``SimplePath`` objects, it should implement this method
+ to resolve such objects.
+
+ Some Distribution providers may elect not to resolve SimplePath
+ objects within the distribution by raising a
+ NotImplementedError, but consumers of such a Distribution would
+ be unable to invoke ``Distribution.files()``.
"""
@classmethod
@@ -639,6 +672,9 @@ class Distribution(metaclass=abc.ABCMeta):
return self._load_json('direct_url.json')
def _load_json(self, filename):
+ # Deferred for performance (python/importlib_metadata#503)
+ import json
+
return pass_none(json.loads)(
self.read_text(filename),
object_hook=lambda data: types.SimpleNamespace(**data),
@@ -723,7 +759,7 @@ class FastPath:
True
"""
- @functools.lru_cache() # type: ignore
+ @functools.lru_cache() # type: ignore[misc]
def __new__(cls, root):
return super().__new__(cls)
@@ -741,7 +777,10 @@ class FastPath:
return []
def zip_children(self):
- zip_path = zipp.Path(self.root)
+ # deferred for performance (python/importlib_metadata#502)
+ from zipp.compat.overlay import zipfile
+
+ zip_path = zipfile.Path(self.root)
names = zip_path.root.namelist()
self.joinpath = zip_path.joinpath
@@ -1078,11 +1117,10 @@ def _get_toplevel_name(name: PackagePath) -> str:
>>> _get_toplevel_name(PackagePath('foo.dist-info'))
'foo.dist-info'
"""
- return _topmost(name) or (
- # python/typeshed#10328
- inspect.getmodulename(name) # type: ignore
- or str(name)
- )
+ # Defer import of inspect for performance (python/cpython#118761)
+ import inspect
+
+ return _topmost(name) or inspect.getmodulename(name) or str(name)
def _top_level_inferred(dist):
diff --git a/lib/importlib_metadata/_adapters.py b/lib/importlib_metadata/_adapters.py
index 6223263e..3b516a2d 100644
--- a/lib/importlib_metadata/_adapters.py
+++ b/lib/importlib_metadata/_adapters.py
@@ -1,6 +1,6 @@
+import email.message
import re
import textwrap
-import email.message
from ._text import FoldedCase
diff --git a/lib/importlib_metadata/_compat.py b/lib/importlib_metadata/_compat.py
index df312b1c..01356d69 100644
--- a/lib/importlib_metadata/_compat.py
+++ b/lib/importlib_metadata/_compat.py
@@ -1,6 +1,5 @@
-import sys
import platform
-
+import sys
__all__ = ['install', 'NullFinder']
diff --git a/lib/importlib_metadata/_functools.py b/lib/importlib_metadata/_functools.py
index 71f66bd0..5dda6a21 100644
--- a/lib/importlib_metadata/_functools.py
+++ b/lib/importlib_metadata/_functools.py
@@ -1,5 +1,5 @@
-import types
import functools
+import types
# from jaraco.functools 3.3
diff --git a/lib/importlib_metadata/_meta.py b/lib/importlib_metadata/_meta.py
index 1927d0f6..0942bbd9 100644
--- a/lib/importlib_metadata/_meta.py
+++ b/lib/importlib_metadata/_meta.py
@@ -1,9 +1,17 @@
from __future__ import annotations
import os
-from typing import Protocol
-from typing import Any, Dict, Iterator, List, Optional, TypeVar, Union, overload
-
+from typing import (
+ Any,
+ Dict,
+ Iterator,
+ List,
+ Optional,
+ Protocol,
+ TypeVar,
+ Union,
+ overload,
+)
_T = TypeVar("_T")
diff --git a/lib/importlib_resources/__init__.py b/lib/importlib_resources/__init__.py
index 0d029abd..723c9f9e 100644
--- a/lib/importlib_resources/__init__.py
+++ b/lib/importlib_resources/__init__.py
@@ -1,4 +1,11 @@
-"""Read resources contained within a package."""
+"""
+Read resources contained within a package.
+
+This codebase is shared between importlib.resources in the stdlib
+and importlib_resources in PyPI. See
+https://github.com/python/importlib_metadata/wiki/Development-Methodology
+for more detail.
+"""
from ._common import (
as_file,
@@ -7,7 +14,7 @@ from ._common import (
Anchor,
)
-from .functional import (
+from ._functional import (
contents,
is_resource,
open_binary,
diff --git a/lib/importlib_resources/_common.py b/lib/importlib_resources/_common.py
index 8df6b39e..f065d493 100644
--- a/lib/importlib_resources/_common.py
+++ b/lib/importlib_resources/_common.py
@@ -66,10 +66,10 @@ def get_resource_reader(package: types.ModuleType) -> Optional[ResourceReader]:
# zipimport.zipimporter does not support weak references, resulting in a
# TypeError. That seems terrible.
spec = package.__spec__
- reader = getattr(spec.loader, 'get_resource_reader', None) # type: ignore
+ reader = getattr(spec.loader, 'get_resource_reader', None) # type: ignore[union-attr]
if reader is None:
return None
- return reader(spec.name) # type: ignore
+ return reader(spec.name) # type: ignore[union-attr]
@functools.singledispatch
@@ -93,12 +93,13 @@ def _infer_caller():
"""
def is_this_file(frame_info):
- return frame_info.filename == __file__
+ return frame_info.filename == stack[0].filename
def is_wrapper(frame_info):
return frame_info.function == 'wrapper'
- not_this_file = itertools.filterfalse(is_this_file, inspect.stack())
+ stack = inspect.stack()
+ not_this_file = itertools.filterfalse(is_this_file, stack)
# also exclude 'wrapper' due to singledispatch in the call stack
callers = itertools.filterfalse(is_wrapper, not_this_file)
return next(callers).frame
@@ -182,7 +183,7 @@ def _(path):
@contextlib.contextmanager
def _temp_path(dir: tempfile.TemporaryDirectory):
"""
- Wrap tempfile.TemporyDirectory to return a pathlib object.
+ Wrap tempfile.TemporaryDirectory to return a pathlib object.
"""
with dir as result:
yield pathlib.Path(result)
diff --git a/lib/importlib_resources/functional.py b/lib/importlib_resources/_functional.py
similarity index 100%
rename from lib/importlib_resources/functional.py
rename to lib/importlib_resources/_functional.py
diff --git a/lib/importlib_resources/compat/py39.py b/lib/importlib_resources/compat/py39.py
index ab87b9dc..ed5abd5e 100644
--- a/lib/importlib_resources/compat/py39.py
+++ b/lib/importlib_resources/compat/py39.py
@@ -5,6 +5,6 @@ __all__ = ['ZipPath']
if sys.version_info >= (3, 10):
- from zipfile import Path as ZipPath # type: ignore
+ from zipfile import Path as ZipPath
else:
- from zipp import Path as ZipPath # type: ignore
+ from zipp import Path as ZipPath
diff --git a/lib/importlib_resources/readers.py b/lib/importlib_resources/readers.py
index 4a80a774..4f761c64 100644
--- a/lib/importlib_resources/readers.py
+++ b/lib/importlib_resources/readers.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
import collections
import contextlib
import itertools
@@ -5,6 +7,7 @@ import pathlib
import operator
import re
import warnings
+from collections.abc import Iterator
from . import abc
@@ -34,8 +37,10 @@ class FileReader(abc.TraversableResources):
class ZipReader(abc.TraversableResources):
def __init__(self, loader, module):
- _, _, name = module.rpartition('.')
- self.prefix = loader.prefix.replace('\\', '/') + name + '/'
+ self.prefix = loader.prefix.replace('\\', '/')
+ if loader.is_package(module):
+ _, _, name = module.rpartition('.')
+ self.prefix += name + '/'
self.archive = loader.archive
def open_resource(self, resource):
@@ -133,27 +138,31 @@ class NamespaceReader(abc.TraversableResources):
def __init__(self, namespace_path):
if 'NamespacePath' not in str(namespace_path):
raise ValueError('Invalid path')
- self.path = MultiplexedPath(*map(self._resolve, namespace_path))
+ self.path = MultiplexedPath(*filter(bool, map(self._resolve, namespace_path)))
@classmethod
- def _resolve(cls, path_str) -> abc.Traversable:
+ def _resolve(cls, path_str) -> abc.Traversable | None:
r"""
Given an item from a namespace path, resolve it to a Traversable.
path_str might be a directory on the filesystem or a path to a
zipfile plus the path within the zipfile, e.g. ``/foo/bar`` or
``/foo/baz.zip/inner_dir`` or ``foo\baz.zip\inner_dir\sub``.
+
+ path_str might also be a sentinel used by editable packages to
+ trigger other behaviors (see python/importlib_resources#311).
+ In that case, return None.
"""
- (dir,) = (cand for cand in cls._candidate_paths(path_str) if cand.is_dir())
- return dir
+ dirs = (cand for cand in cls._candidate_paths(path_str) if cand.is_dir())
+ return next(dirs, None)
@classmethod
- def _candidate_paths(cls, path_str):
+ def _candidate_paths(cls, path_str: str) -> Iterator[abc.Traversable]:
yield pathlib.Path(path_str)
yield from cls._resolve_zip_path(path_str)
@staticmethod
- def _resolve_zip_path(path_str):
+ def _resolve_zip_path(path_str: str):
for match in reversed(list(re.finditer(r'[\\/]', path_str))):
with contextlib.suppress(
FileNotFoundError,
diff --git a/lib/importlib_resources/simple.py b/lib/importlib_resources/simple.py
index 96f117fe..2e75299b 100644
--- a/lib/importlib_resources/simple.py
+++ b/lib/importlib_resources/simple.py
@@ -77,7 +77,7 @@ class ResourceHandle(Traversable):
def __init__(self, parent: ResourceContainer, name: str):
self.parent = parent
- self.name = name # type: ignore
+ self.name = name # type: ignore[misc]
def is_file(self):
return True
diff --git a/lib/importlib_resources/tests/_path.py b/lib/importlib_resources/tests/_path.py
index 1f97c961..b144628c 100644
--- a/lib/importlib_resources/tests/_path.py
+++ b/lib/importlib_resources/tests/_path.py
@@ -2,15 +2,44 @@ import pathlib
import functools
from typing import Dict, Union
+from typing import runtime_checkable
+from typing import Protocol
####
-# from jaraco.path 3.4.1
-
-FilesSpec = Dict[str, Union[str, bytes, 'FilesSpec']] # type: ignore
+# from jaraco.path 3.7.1
-def build(spec: FilesSpec, prefix=pathlib.Path()):
+class Symlink(str):
+ """
+ A string indicating the target of a symlink.
+ """
+
+
+FilesSpec = Dict[str, Union[str, bytes, Symlink, 'FilesSpec']]
+
+
+@runtime_checkable
+class TreeMaker(Protocol):
+ def __truediv__(self, *args, **kwargs): ... # pragma: no cover
+
+ def mkdir(self, **kwargs): ... # pragma: no cover
+
+ def write_text(self, content, **kwargs): ... # pragma: no cover
+
+ def write_bytes(self, content): ... # pragma: no cover
+
+ def symlink_to(self, target): ... # pragma: no cover
+
+
+def _ensure_tree_maker(obj: Union[str, TreeMaker]) -> TreeMaker:
+ return obj if isinstance(obj, TreeMaker) else pathlib.Path(obj) # type: ignore[return-value]
+
+
+def build(
+ spec: FilesSpec,
+ prefix: Union[str, TreeMaker] = pathlib.Path(), # type: ignore[assignment]
+):
"""
Build a set of files/directories, as described by the spec.
@@ -25,21 +54,25 @@ def build(spec: FilesSpec, prefix=pathlib.Path()):
... "__init__.py": "",
... },
... "baz.py": "# Some code",
- ... }
+ ... "bar.py": Symlink("baz.py"),
+ ... },
+ ... "bing": Symlink("foo"),
... }
>>> target = getfixture('tmp_path')
>>> build(spec, target)
>>> target.joinpath('foo/baz.py').read_text(encoding='utf-8')
'# Some code'
+ >>> target.joinpath('bing/bar.py').read_text(encoding='utf-8')
+ '# Some code'
"""
for name, contents in spec.items():
- create(contents, pathlib.Path(prefix) / name)
+ create(contents, _ensure_tree_maker(prefix) / name)
@functools.singledispatch
def create(content: Union[str, bytes, FilesSpec], path):
path.mkdir(exist_ok=True)
- build(content, prefix=path) # type: ignore
+ build(content, prefix=path) # type: ignore[arg-type]
@create.register
@@ -52,5 +85,10 @@ def _(content: str, path):
path.write_text(content, encoding='utf-8')
+@create.register
+def _(content: Symlink, path):
+ path.symlink_to(content)
+
+
# end from jaraco.path
####
diff --git a/lib/importlib_resources/tests/compat/py39.py b/lib/importlib_resources/tests/compat/py39.py
index e158eb85..e01d276b 100644
--- a/lib/importlib_resources/tests/compat/py39.py
+++ b/lib/importlib_resources/tests/compat/py39.py
@@ -8,3 +8,6 @@ import_helper = try_import('import_helper') or from_test_support(
'modules_setup', 'modules_cleanup', 'DirsOnSysPath'
)
os_helper = try_import('os_helper') or from_test_support('temp_dir')
+warnings_helper = try_import('warnings_helper') or from_test_support(
+ 'ignore_warnings', 'check_warnings'
+)
diff --git a/lib/importlib_resources/tests/data01/__init__.py b/lib/importlib_resources/tests/data01/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/lib/importlib_resources/tests/data01/binary.file b/lib/importlib_resources/tests/data01/binary.file
deleted file mode 100644
index eaf36c1d..00000000
Binary files a/lib/importlib_resources/tests/data01/binary.file and /dev/null differ
diff --git a/lib/importlib_resources/tests/data01/subdirectory/__init__.py b/lib/importlib_resources/tests/data01/subdirectory/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/lib/importlib_resources/tests/data01/subdirectory/binary.file b/lib/importlib_resources/tests/data01/subdirectory/binary.file
deleted file mode 100644
index 5bd8bb89..00000000
--- a/lib/importlib_resources/tests/data01/subdirectory/binary.file
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/lib/importlib_resources/tests/data01/utf-16.file b/lib/importlib_resources/tests/data01/utf-16.file
deleted file mode 100644
index 2cb77229..00000000
Binary files a/lib/importlib_resources/tests/data01/utf-16.file and /dev/null differ
diff --git a/lib/importlib_resources/tests/data01/utf-8.file b/lib/importlib_resources/tests/data01/utf-8.file
deleted file mode 100644
index 1c0132ad..00000000
--- a/lib/importlib_resources/tests/data01/utf-8.file
+++ /dev/null
@@ -1 +0,0 @@
-Hello, UTF-8 world!
diff --git a/lib/importlib_resources/tests/data02/__init__.py b/lib/importlib_resources/tests/data02/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/lib/importlib_resources/tests/data02/one/__init__.py b/lib/importlib_resources/tests/data02/one/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/lib/importlib_resources/tests/data02/one/resource1.txt b/lib/importlib_resources/tests/data02/one/resource1.txt
deleted file mode 100644
index 61a813e4..00000000
--- a/lib/importlib_resources/tests/data02/one/resource1.txt
+++ /dev/null
@@ -1 +0,0 @@
-one resource
diff --git a/lib/importlib_resources/tests/data02/subdirectory/subsubdir/resource.txt b/lib/importlib_resources/tests/data02/subdirectory/subsubdir/resource.txt
deleted file mode 100644
index 48f587a2..00000000
--- a/lib/importlib_resources/tests/data02/subdirectory/subsubdir/resource.txt
+++ /dev/null
@@ -1 +0,0 @@
-a resource
\ No newline at end of file
diff --git a/lib/importlib_resources/tests/data02/two/__init__.py b/lib/importlib_resources/tests/data02/two/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/lib/importlib_resources/tests/data02/two/resource2.txt b/lib/importlib_resources/tests/data02/two/resource2.txt
deleted file mode 100644
index a80ce46e..00000000
--- a/lib/importlib_resources/tests/data02/two/resource2.txt
+++ /dev/null
@@ -1 +0,0 @@
-two resource
diff --git a/lib/importlib_resources/tests/namespacedata01/binary.file b/lib/importlib_resources/tests/namespacedata01/binary.file
deleted file mode 100644
index eaf36c1d..00000000
Binary files a/lib/importlib_resources/tests/namespacedata01/binary.file and /dev/null differ
diff --git a/lib/importlib_resources/tests/namespacedata01/subdirectory/binary.file b/lib/importlib_resources/tests/namespacedata01/subdirectory/binary.file
deleted file mode 100644
index 100f5064..00000000
--- a/lib/importlib_resources/tests/namespacedata01/subdirectory/binary.file
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/lib/importlib_resources/tests/namespacedata01/utf-16.file b/lib/importlib_resources/tests/namespacedata01/utf-16.file
deleted file mode 100644
index 2cb77229..00000000
Binary files a/lib/importlib_resources/tests/namespacedata01/utf-16.file and /dev/null differ
diff --git a/lib/importlib_resources/tests/namespacedata01/utf-8.file b/lib/importlib_resources/tests/namespacedata01/utf-8.file
deleted file mode 100644
index 1c0132ad..00000000
--- a/lib/importlib_resources/tests/namespacedata01/utf-8.file
+++ /dev/null
@@ -1 +0,0 @@
-Hello, UTF-8 world!
diff --git a/lib/importlib_resources/tests/test_contents.py b/lib/importlib_resources/tests/test_contents.py
index 7dc3b0a6..741a7407 100644
--- a/lib/importlib_resources/tests/test_contents.py
+++ b/lib/importlib_resources/tests/test_contents.py
@@ -1,7 +1,6 @@
import unittest
import importlib_resources as resources
-from . import data01
from . import util
@@ -19,16 +18,17 @@ class ContentsTests:
assert self.expected <= contents
-class ContentsDiskTests(ContentsTests, unittest.TestCase):
- def setUp(self):
- self.data = data01
+class ContentsDiskTests(ContentsTests, util.DiskSetup, unittest.TestCase):
+ pass
class ContentsZipTests(ContentsTests, util.ZipSetup, unittest.TestCase):
pass
-class ContentsNamespaceTests(ContentsTests, unittest.TestCase):
+class ContentsNamespaceTests(ContentsTests, util.DiskSetup, unittest.TestCase):
+ MODULE = 'namespacedata01'
+
expected = {
# no __init__ because of namespace design
'binary.file',
@@ -36,8 +36,3 @@ class ContentsNamespaceTests(ContentsTests, unittest.TestCase):
'utf-16.file',
'utf-8.file',
}
-
- def setUp(self):
- from . import namespacedata01
-
- self.data = namespacedata01
diff --git a/lib/importlib_resources/tests/test_files.py b/lib/importlib_resources/tests/test_files.py
index 3e86ec64..f1fe2337 100644
--- a/lib/importlib_resources/tests/test_files.py
+++ b/lib/importlib_resources/tests/test_files.py
@@ -1,3 +1,7 @@
+import os
+import pathlib
+import py_compile
+import shutil
import textwrap
import unittest
import warnings
@@ -6,11 +10,8 @@ import contextlib
import importlib_resources as resources
from ..abc import Traversable
-from . import data01
from . import util
-from . import _path
-from .compat.py39 import os_helper
-from .compat.py312 import import_helper
+from .compat.py39 import os_helper, import_helper
@contextlib.contextmanager
@@ -48,70 +49,146 @@ class FilesTests:
resources.files(package=self.data)
-class OpenDiskTests(FilesTests, unittest.TestCase):
- def setUp(self):
- self.data = data01
+class OpenDiskTests(FilesTests, util.DiskSetup, unittest.TestCase):
+ pass
class OpenZipTests(FilesTests, util.ZipSetup, unittest.TestCase):
pass
-class OpenNamespaceTests(FilesTests, unittest.TestCase):
- def setUp(self):
- from . import namespacedata01
+class OpenNamespaceTests(FilesTests, util.DiskSetup, unittest.TestCase):
+ MODULE = 'namespacedata01'
- self.data = namespacedata01
+ def test_non_paths_in_dunder_path(self):
+ """
+ Non-path items in a namespace package's ``__path__`` are ignored.
+
+ As reported in python/importlib_resources#311, some tools
+ like Setuptools, when creating editable packages, will inject
+ non-paths into a namespace package's ``__path__``, a
+ sentinel like
+ ``__editable__.sample_namespace-1.0.finder.__path_hook__``
+ to cause the ``PathEntryFinder`` to be called when searching
+ for packages. In that case, resources should still be loadable.
+ """
+ import namespacedata01
+
+ namespacedata01.__path__.append(
+ '__editable__.sample_namespace-1.0.finder.__path_hook__'
+ )
+
+ resources.files(namespacedata01)
class OpenNamespaceZipTests(FilesTests, util.ZipSetup, unittest.TestCase):
ZIP_MODULE = 'namespacedata01'
-class SiteDir:
- def setUp(self):
- self.fixtures = contextlib.ExitStack()
- self.addCleanup(self.fixtures.close)
- self.site_dir = self.fixtures.enter_context(os_helper.temp_dir())
- self.fixtures.enter_context(import_helper.DirsOnSysPath(self.site_dir))
- self.fixtures.enter_context(import_helper.isolated_modules())
+class DirectSpec:
+ """
+ Override behavior of ModuleSetup to write a full spec directly.
+ """
+
+ MODULE = 'unused'
+
+ def load_fixture(self, name):
+ self.tree_on_path(self.spec)
-class ModulesFilesTests(SiteDir, unittest.TestCase):
+class ModulesFiles:
+ spec = {
+ 'mod.py': '',
+ 'res.txt': 'resources are the best',
+ }
+
def test_module_resources(self):
"""
A module can have resources found adjacent to the module.
"""
- spec = {
- 'mod.py': '',
- 'res.txt': 'resources are the best',
- }
- _path.build(spec, self.site_dir)
- import mod
+ import mod # type: ignore[import-not-found]
actual = resources.files(mod).joinpath('res.txt').read_text(encoding='utf-8')
- assert actual == spec['res.txt']
+ assert actual == self.spec['res.txt']
-class ImplicitContextFilesTests(SiteDir, unittest.TestCase):
- def test_implicit_files(self):
+class ModuleFilesDiskTests(DirectSpec, util.DiskSetup, ModulesFiles, unittest.TestCase):
+ pass
+
+
+class ModuleFilesZipTests(DirectSpec, util.ZipSetup, ModulesFiles, unittest.TestCase):
+ pass
+
+
+class ImplicitContextFiles:
+ set_val = textwrap.dedent(
+ f"""
+ import {resources.__name__} as res
+ val = res.files().joinpath('res.txt').read_text(encoding='utf-8')
+ """
+ )
+ spec = {
+ 'somepkg': {
+ '__init__.py': set_val,
+ 'submod.py': set_val,
+ 'res.txt': 'resources are the best',
+ },
+ 'frozenpkg': {
+ '__init__.py': set_val.replace(resources.__name__, 'c_resources'),
+ 'res.txt': 'resources are the best',
+ },
+ }
+
+ def test_implicit_files_package(self):
"""
Without any parameter, files() will infer the location as the caller.
"""
- spec = {
- 'somepkg': {
- '__init__.py': textwrap.dedent(
- """
- import importlib_resources as res
- val = res.files().joinpath('res.txt').read_text(encoding='utf-8')
- """
- ),
- 'res.txt': 'resources are the best',
- },
- }
- _path.build(spec, self.site_dir)
assert importlib.import_module('somepkg').val == 'resources are the best'
+ def test_implicit_files_submodule(self):
+ """
+ Without any parameter, files() will infer the location as the caller.
+ """
+ assert importlib.import_module('somepkg.submod').val == 'resources are the best'
+
+ def _compile_importlib(self):
+ """
+ Make a compiled-only copy of the importlib resources package.
+ """
+ bin_site = self.fixtures.enter_context(os_helper.temp_dir())
+ c_resources = pathlib.Path(bin_site, 'c_resources')
+ sources = pathlib.Path(resources.__file__).parent
+ shutil.copytree(sources, c_resources, ignore=lambda *_: ['__pycache__'])
+
+ for dirpath, _, filenames in os.walk(c_resources):
+ for filename in filenames:
+ source_path = pathlib.Path(dirpath) / filename
+ cfile = source_path.with_suffix('.pyc')
+ py_compile.compile(source_path, cfile)
+ pathlib.Path.unlink(source_path)
+ self.fixtures.enter_context(import_helper.DirsOnSysPath(bin_site))
+
+ def test_implicit_files_with_compiled_importlib(self):
+ """
+ Caller detection works for compiled-only resources module.
+
+ python/cpython#123085
+ """
+ self._compile_importlib()
+ assert importlib.import_module('frozenpkg').val == 'resources are the best'
+
+
+class ImplicitContextFilesDiskTests(
+ DirectSpec, util.DiskSetup, ImplicitContextFiles, unittest.TestCase
+):
+ pass
+
+
+class ImplicitContextFilesZipTests(
+ DirectSpec, util.ZipSetup, ImplicitContextFiles, unittest.TestCase
+):
+ pass
+
if __name__ == '__main__':
unittest.main()
diff --git a/lib/importlib_resources/tests/test_functional.py b/lib/importlib_resources/tests/test_functional.py
index 69706cf7..1851edfb 100644
--- a/lib/importlib_resources/tests/test_functional.py
+++ b/lib/importlib_resources/tests/test_functional.py
@@ -1,31 +1,38 @@
import unittest
import os
-import contextlib
+import importlib
-try:
- from test.support.warnings_helper import ignore_warnings, check_warnings
-except ImportError:
- # older Python versions
- from test.support import ignore_warnings, check_warnings
+from .compat.py39 import warnings_helper
import importlib_resources as resources
+from . import util
+
# Since the functional API forwards to Traversable, we only test
# filesystem resources here -- not zip files, namespace packages etc.
# We do test for two kinds of Anchor, though.
class StringAnchorMixin:
- anchor01 = 'importlib_resources.tests.data01'
- anchor02 = 'importlib_resources.tests.data02'
+ anchor01 = 'data01'
+ anchor02 = 'data02'
class ModuleAnchorMixin:
- from . import data01 as anchor01
- from . import data02 as anchor02
+ @property
+ def anchor01(self):
+ return importlib.import_module('data01')
+
+ @property
+ def anchor02(self):
+ return importlib.import_module('data02')
-class FunctionalAPIBase:
+class FunctionalAPIBase(util.DiskSetup):
+ def setUp(self):
+ super().setUp()
+ self.load_fixture('data02')
+
def _gen_resourcetxt_path_parts(self):
"""Yield various names of a text file in anchor02, each in a subTest"""
for path_parts in (
@@ -36,6 +43,12 @@ class FunctionalAPIBase:
with self.subTest(path_parts=path_parts):
yield path_parts
+ def assertEndsWith(self, string, suffix):
+ """Assert that `string` ends with `suffix`.
+
+ Used to ignore an architecture-specific UTF-16 byte-order mark."""
+ self.assertEqual(string[-len(suffix) :], suffix)
+
def test_read_text(self):
self.assertEqual(
resources.read_text(self.anchor01, 'utf-8.file'),
@@ -76,13 +89,13 @@ class FunctionalAPIBase:
),
'\x00\x01\x02\x03',
)
- self.assertEqual(
+ self.assertEndsWith( # ignore the BOM
resources.read_text(
self.anchor01,
'utf-16.file',
errors='backslashreplace',
),
- 'Hello, UTF-16 world!\n'.encode('utf-16').decode(
+ 'Hello, UTF-16 world!\n'.encode('utf-16-le').decode(
errors='backslashreplace',
),
)
@@ -128,9 +141,9 @@ class FunctionalAPIBase:
'utf-16.file',
errors='backslashreplace',
) as f:
- self.assertEqual(
+ self.assertEndsWith( # ignore the BOM
f.read(),
- 'Hello, UTF-16 world!\n'.encode('utf-16').decode(
+ 'Hello, UTF-16 world!\n'.encode('utf-16-le').decode(
errors='backslashreplace',
),
)
@@ -163,32 +176,32 @@ class FunctionalAPIBase:
self.assertTrue(is_resource(self.anchor02, *path_parts))
def test_contents(self):
- with check_warnings((".*contents.*", DeprecationWarning)):
+ with warnings_helper.check_warnings((".*contents.*", DeprecationWarning)):
c = resources.contents(self.anchor01)
self.assertGreaterEqual(
set(c),
{'utf-8.file', 'utf-16.file', 'binary.file', 'subdirectory'},
)
- with contextlib.ExitStack() as cm:
- cm.enter_context(self.assertRaises(OSError))
- cm.enter_context(check_warnings((".*contents.*", DeprecationWarning)))
-
+ with self.assertRaises(OSError), warnings_helper.check_warnings((
+ ".*contents.*",
+ DeprecationWarning,
+ )):
list(resources.contents(self.anchor01, 'utf-8.file'))
for path_parts in self._gen_resourcetxt_path_parts():
- with contextlib.ExitStack() as cm:
- cm.enter_context(self.assertRaises(OSError))
- cm.enter_context(check_warnings((".*contents.*", DeprecationWarning)))
-
+ with self.assertRaises(OSError), warnings_helper.check_warnings((
+ ".*contents.*",
+ DeprecationWarning,
+ )):
list(resources.contents(self.anchor01, *path_parts))
- with check_warnings((".*contents.*", DeprecationWarning)):
+ with warnings_helper.check_warnings((".*contents.*", DeprecationWarning)):
c = resources.contents(self.anchor01, 'subdirectory')
self.assertGreaterEqual(
set(c),
{'binary.file'},
)
- @ignore_warnings(category=DeprecationWarning)
+ @warnings_helper.ignore_warnings(category=DeprecationWarning)
def test_common_errors(self):
for func in (
resources.read_text,
@@ -227,16 +240,16 @@ class FunctionalAPIBase:
class FunctionalAPITest_StringAnchor(
- unittest.TestCase,
- FunctionalAPIBase,
StringAnchorMixin,
+ FunctionalAPIBase,
+ unittest.TestCase,
):
pass
class FunctionalAPITest_ModuleAnchor(
- unittest.TestCase,
- FunctionalAPIBase,
ModuleAnchorMixin,
+ FunctionalAPIBase,
+ unittest.TestCase,
):
pass
diff --git a/lib/importlib_resources/tests/test_open.py b/lib/importlib_resources/tests/test_open.py
index 44f1018a..c40bb8c6 100644
--- a/lib/importlib_resources/tests/test_open.py
+++ b/lib/importlib_resources/tests/test_open.py
@@ -1,7 +1,6 @@
import unittest
import importlib_resources as resources
-from . import data01
from . import util
@@ -65,16 +64,12 @@ class OpenTests:
target.open(encoding='utf-8')
-class OpenDiskTests(OpenTests, unittest.TestCase):
- def setUp(self):
- self.data = data01
+class OpenDiskTests(OpenTests, util.DiskSetup, unittest.TestCase):
+ pass
-class OpenDiskNamespaceTests(OpenTests, unittest.TestCase):
- def setUp(self):
- from . import namespacedata01
-
- self.data = namespacedata01
+class OpenDiskNamespaceTests(OpenTests, util.DiskSetup, unittest.TestCase):
+ MODULE = 'namespacedata01'
class OpenZipTests(OpenTests, util.ZipSetup, unittest.TestCase):
@@ -82,7 +77,7 @@ class OpenZipTests(OpenTests, util.ZipSetup, unittest.TestCase):
class OpenNamespaceZipTests(OpenTests, util.ZipSetup, unittest.TestCase):
- ZIP_MODULE = 'namespacedata01'
+ MODULE = 'namespacedata01'
if __name__ == '__main__':
diff --git a/lib/importlib_resources/tests/test_path.py b/lib/importlib_resources/tests/test_path.py
index c3e1cbb4..1e30f2bc 100644
--- a/lib/importlib_resources/tests/test_path.py
+++ b/lib/importlib_resources/tests/test_path.py
@@ -3,7 +3,6 @@ import pathlib
import unittest
import importlib_resources as resources
-from . import data01
from . import util
@@ -25,9 +24,7 @@ class PathTests:
self.assertEqual('Hello, UTF-8 world!\n', path.read_text(encoding='utf-8'))
-class PathDiskTests(PathTests, unittest.TestCase):
- data = data01
-
+class PathDiskTests(PathTests, util.DiskSetup, unittest.TestCase):
def test_natural_path(self):
"""
Guarantee the internal implementation detail that
diff --git a/lib/importlib_resources/tests/test_read.py b/lib/importlib_resources/tests/test_read.py
index 97d90128..6780a2d1 100644
--- a/lib/importlib_resources/tests/test_read.py
+++ b/lib/importlib_resources/tests/test_read.py
@@ -1,7 +1,6 @@
import unittest
import importlib_resources as resources
-from . import data01
from . import util
from importlib import import_module
@@ -52,8 +51,8 @@ class ReadTests:
)
-class ReadDiskTests(ReadTests, unittest.TestCase):
- data = data01
+class ReadDiskTests(ReadTests, util.DiskSetup, unittest.TestCase):
+ pass
class ReadZipTests(ReadTests, util.ZipSetup, unittest.TestCase):
@@ -69,15 +68,12 @@ class ReadZipTests(ReadTests, util.ZipSetup, unittest.TestCase):
self.assertEqual(result, bytes(range(4, 8)))
-class ReadNamespaceTests(ReadTests, unittest.TestCase):
- def setUp(self):
- from . import namespacedata01
-
- self.data = namespacedata01
+class ReadNamespaceTests(ReadTests, util.DiskSetup, unittest.TestCase):
+ MODULE = 'namespacedata01'
class ReadNamespaceZipTests(ReadTests, util.ZipSetup, unittest.TestCase):
- ZIP_MODULE = 'namespacedata01'
+ MODULE = 'namespacedata01'
def test_read_submodule_resource(self):
submodule = import_module('namespacedata01.subdirectory')
diff --git a/lib/importlib_resources/tests/test_reader.py b/lib/importlib_resources/tests/test_reader.py
index 95c2fc85..0a77eb40 100644
--- a/lib/importlib_resources/tests/test_reader.py
+++ b/lib/importlib_resources/tests/test_reader.py
@@ -1,16 +1,21 @@
import os.path
-import sys
import pathlib
import unittest
from importlib import import_module
from importlib_resources.readers import MultiplexedPath, NamespaceReader
+from . import util
-class MultiplexedPathTest(unittest.TestCase):
- @classmethod
- def setUpClass(cls):
- cls.folder = pathlib.Path(__file__).parent / 'namespacedata01'
+
+class MultiplexedPathTest(util.DiskSetup, unittest.TestCase):
+ MODULE = 'namespacedata01'
+
+ def setUp(self):
+ super().setUp()
+ self.folder = pathlib.Path(self.data.__path__[0])
+ self.data01 = pathlib.Path(self.load_fixture('data01').__file__).parent
+ self.data02 = pathlib.Path(self.load_fixture('data02').__file__).parent
def test_init_no_paths(self):
with self.assertRaises(FileNotFoundError):
@@ -31,9 +36,8 @@ class MultiplexedPathTest(unittest.TestCase):
)
def test_iterdir_duplicate(self):
- data01 = pathlib.Path(__file__).parent.joinpath('data01')
contents = {
- path.name for path in MultiplexedPath(self.folder, data01).iterdir()
+ path.name for path in MultiplexedPath(self.folder, self.data01).iterdir()
}
for remove in ('__pycache__', '__init__.pyc'):
try:
@@ -61,9 +65,8 @@ class MultiplexedPathTest(unittest.TestCase):
path.open()
def test_join_path(self):
- data01 = pathlib.Path(__file__).parent.joinpath('data01')
- prefix = str(data01.parent)
- path = MultiplexedPath(self.folder, data01)
+ prefix = str(self.folder.parent)
+ path = MultiplexedPath(self.folder, self.data01)
self.assertEqual(
str(path.joinpath('binary.file'))[len(prefix) + 1 :],
os.path.join('namespacedata01', 'binary.file'),
@@ -83,10 +86,8 @@ class MultiplexedPathTest(unittest.TestCase):
assert not path.joinpath('imaginary/foo.py').exists()
def test_join_path_common_subdir(self):
- data01 = pathlib.Path(__file__).parent.joinpath('data01')
- data02 = pathlib.Path(__file__).parent.joinpath('data02')
- prefix = str(data01.parent)
- path = MultiplexedPath(data01, data02)
+ prefix = str(self.data02.parent)
+ path = MultiplexedPath(self.data01, self.data02)
self.assertIsInstance(path.joinpath('subdirectory'), MultiplexedPath)
self.assertEqual(
str(path.joinpath('subdirectory', 'subsubdir'))[len(prefix) + 1 :],
@@ -106,16 +107,8 @@ class MultiplexedPathTest(unittest.TestCase):
)
-class NamespaceReaderTest(unittest.TestCase):
- site_dir = str(pathlib.Path(__file__).parent)
-
- @classmethod
- def setUpClass(cls):
- sys.path.append(cls.site_dir)
-
- @classmethod
- def tearDownClass(cls):
- sys.path.remove(cls.site_dir)
+class NamespaceReaderTest(util.DiskSetup, unittest.TestCase):
+ MODULE = 'namespacedata01'
def test_init_error(self):
with self.assertRaises(ValueError):
@@ -125,7 +118,7 @@ class NamespaceReaderTest(unittest.TestCase):
namespacedata01 = import_module('namespacedata01')
reader = NamespaceReader(namespacedata01.__spec__.submodule_search_locations)
- root = os.path.abspath(os.path.join(__file__, '..', 'namespacedata01'))
+ root = self.data.__path__[0]
self.assertEqual(
reader.resource_path('binary.file'), os.path.join(root, 'binary.file')
)
@@ -134,9 +127,8 @@ class NamespaceReaderTest(unittest.TestCase):
)
def test_files(self):
- namespacedata01 = import_module('namespacedata01')
- reader = NamespaceReader(namespacedata01.__spec__.submodule_search_locations)
- root = os.path.abspath(os.path.join(__file__, '..', 'namespacedata01'))
+ reader = NamespaceReader(self.data.__spec__.submodule_search_locations)
+ root = self.data.__path__[0]
self.assertIsInstance(reader.files(), MultiplexedPath)
self.assertEqual(repr(reader.files()), f"MultiplexedPath('{root}')")
diff --git a/lib/importlib_resources/tests/test_resource.py b/lib/importlib_resources/tests/test_resource.py
index dc2a108c..a0da6a35 100644
--- a/lib/importlib_resources/tests/test_resource.py
+++ b/lib/importlib_resources/tests/test_resource.py
@@ -1,9 +1,6 @@
-import sys
import unittest
import importlib_resources as resources
-import pathlib
-from . import data01
from . import util
from importlib import import_module
@@ -25,9 +22,8 @@ class ResourceTests:
self.assertTrue(target.is_dir())
-class ResourceDiskTests(ResourceTests, unittest.TestCase):
- def setUp(self):
- self.data = data01
+class ResourceDiskTests(ResourceTests, util.DiskSetup, unittest.TestCase):
+ pass
class ResourceZipTests(ResourceTests, util.ZipSetup, unittest.TestCase):
@@ -38,33 +34,39 @@ def names(traversable):
return {item.name for item in traversable.iterdir()}
-class ResourceLoaderTests(unittest.TestCase):
+class ResourceLoaderTests(util.DiskSetup, unittest.TestCase):
def test_resource_contents(self):
package = util.create_package(
- file=data01, path=data01.__file__, contents=['A', 'B', 'C']
+ file=self.data, path=self.data.__file__, contents=['A', 'B', 'C']
)
self.assertEqual(names(resources.files(package)), {'A', 'B', 'C'})
def test_is_file(self):
package = util.create_package(
- file=data01, path=data01.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F']
+ file=self.data,
+ path=self.data.__file__,
+ contents=['A', 'B', 'C', 'D/E', 'D/F'],
)
self.assertTrue(resources.files(package).joinpath('B').is_file())
def test_is_dir(self):
package = util.create_package(
- file=data01, path=data01.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F']
+ file=self.data,
+ path=self.data.__file__,
+ contents=['A', 'B', 'C', 'D/E', 'D/F'],
)
self.assertTrue(resources.files(package).joinpath('D').is_dir())
def test_resource_missing(self):
package = util.create_package(
- file=data01, path=data01.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F']
+ file=self.data,
+ path=self.data.__file__,
+ contents=['A', 'B', 'C', 'D/E', 'D/F'],
)
self.assertFalse(resources.files(package).joinpath('Z').is_file())
-class ResourceCornerCaseTests(unittest.TestCase):
+class ResourceCornerCaseTests(util.DiskSetup, unittest.TestCase):
def test_package_has_no_reader_fallback(self):
"""
Test odd ball packages which:
@@ -73,7 +75,7 @@ class ResourceCornerCaseTests(unittest.TestCase):
# 3. Are not in a zip file
"""
module = util.create_package(
- file=data01, path=data01.__file__, contents=['A', 'B', 'C']
+ file=self.data, path=self.data.__file__, contents=['A', 'B', 'C']
)
# Give the module a dummy loader.
module.__loader__ = object()
@@ -84,9 +86,7 @@ class ResourceCornerCaseTests(unittest.TestCase):
self.assertFalse(resources.files(module).joinpath('A').is_file())
-class ResourceFromZipsTest01(util.ZipSetupBase, unittest.TestCase):
- ZIP_MODULE = 'data01'
-
+class ResourceFromZipsTest01(util.ZipSetup, unittest.TestCase):
def test_is_submodule_resource(self):
submodule = import_module('data01.subdirectory')
self.assertTrue(resources.files(submodule).joinpath('binary.file').is_file())
@@ -117,8 +117,8 @@ class ResourceFromZipsTest01(util.ZipSetupBase, unittest.TestCase):
assert not data.parent.exists()
-class ResourceFromZipsTest02(util.ZipSetupBase, unittest.TestCase):
- ZIP_MODULE = 'data02'
+class ResourceFromZipsTest02(util.ZipSetup, unittest.TestCase):
+ MODULE = 'data02'
def test_unrelated_contents(self):
"""
@@ -135,7 +135,7 @@ class ResourceFromZipsTest02(util.ZipSetupBase, unittest.TestCase):
)
-class DeletingZipsTest(util.ZipSetupBase, unittest.TestCase):
+class DeletingZipsTest(util.ZipSetup, unittest.TestCase):
"""Having accessed resources in a zip file should not keep an open
reference to the zip.
"""
@@ -217,24 +217,20 @@ class ResourceFromNamespaceTests:
self.assertEqual(contents, {'binary.file'})
-class ResourceFromNamespaceDiskTests(ResourceFromNamespaceTests, unittest.TestCase):
- site_dir = str(pathlib.Path(__file__).parent)
-
- @classmethod
- def setUpClass(cls):
- sys.path.append(cls.site_dir)
-
- @classmethod
- def tearDownClass(cls):
- sys.path.remove(cls.site_dir)
-
-
-class ResourceFromNamespaceZipTests(
- util.ZipSetupBase,
+class ResourceFromNamespaceDiskTests(
+ util.DiskSetup,
ResourceFromNamespaceTests,
unittest.TestCase,
):
- ZIP_MODULE = 'namespacedata01'
+ MODULE = 'namespacedata01'
+
+
+class ResourceFromNamespaceZipTests(
+ util.ZipSetup,
+ ResourceFromNamespaceTests,
+ unittest.TestCase,
+):
+ MODULE = 'namespacedata01'
if __name__ == '__main__':
diff --git a/lib/importlib_resources/tests/util.py b/lib/importlib_resources/tests/util.py
index fb827d2f..a4eafac3 100644
--- a/lib/importlib_resources/tests/util.py
+++ b/lib/importlib_resources/tests/util.py
@@ -6,10 +6,10 @@ import types
import pathlib
import contextlib
-from . import data01
from ..abc import ResourceReader
from .compat.py39 import import_helper, os_helper
from . import zip as zip_
+from . import _path
from importlib.machinery import ModuleSpec
@@ -68,7 +68,7 @@ def create_package(file=None, path=None, is_package=True, contents=()):
)
-class CommonTests(metaclass=abc.ABCMeta):
+class CommonTestsBase(metaclass=abc.ABCMeta):
"""
Tests shared by test_open, test_path, and test_read.
"""
@@ -84,34 +84,34 @@ class CommonTests(metaclass=abc.ABCMeta):
"""
Passing in the package name should succeed.
"""
- self.execute(data01.__name__, 'utf-8.file')
+ self.execute(self.data.__name__, 'utf-8.file')
def test_package_object(self):
"""
Passing in the package itself should succeed.
"""
- self.execute(data01, 'utf-8.file')
+ self.execute(self.data, 'utf-8.file')
def test_string_path(self):
"""
Passing in a string for the path should succeed.
"""
path = 'utf-8.file'
- self.execute(data01, path)
+ self.execute(self.data, path)
def test_pathlib_path(self):
"""
Passing in a pathlib.PurePath object for the path should succeed.
"""
path = pathlib.PurePath('utf-8.file')
- self.execute(data01, path)
+ self.execute(self.data, path)
def test_importing_module_as_side_effect(self):
"""
The anchor package can already be imported.
"""
- del sys.modules[data01.__name__]
- self.execute(data01.__name__, 'utf-8.file')
+ del sys.modules[self.data.__name__]
+ self.execute(self.data.__name__, 'utf-8.file')
def test_missing_path(self):
"""
@@ -141,24 +141,66 @@ class CommonTests(metaclass=abc.ABCMeta):
self.execute(package, 'utf-8.file')
-class ZipSetupBase:
- ZIP_MODULE = 'data01'
+fixtures = dict(
+ data01={
+ '__init__.py': '',
+ 'binary.file': bytes(range(4)),
+ 'utf-16.file': 'Hello, UTF-16 world!\n'.encode('utf-16'),
+ 'utf-8.file': 'Hello, UTF-8 world!\n'.encode('utf-8'),
+ 'subdirectory': {
+ '__init__.py': '',
+ 'binary.file': bytes(range(4, 8)),
+ },
+ },
+ data02={
+ '__init__.py': '',
+ 'one': {'__init__.py': '', 'resource1.txt': 'one resource'},
+ 'two': {'__init__.py': '', 'resource2.txt': 'two resource'},
+ 'subdirectory': {'subsubdir': {'resource.txt': 'a resource'}},
+ },
+ namespacedata01={
+ 'binary.file': bytes(range(4)),
+ 'utf-16.file': 'Hello, UTF-16 world!\n'.encode('utf-16'),
+ 'utf-8.file': 'Hello, UTF-8 world!\n'.encode('utf-8'),
+ 'subdirectory': {
+ 'binary.file': bytes(range(12, 16)),
+ },
+ },
+)
+
+class ModuleSetup:
def setUp(self):
self.fixtures = contextlib.ExitStack()
self.addCleanup(self.fixtures.close)
self.fixtures.enter_context(import_helper.isolated_modules())
+ self.data = self.load_fixture(self.MODULE)
+ def load_fixture(self, module):
+ self.tree_on_path({module: fixtures[module]})
+ return importlib.import_module(module)
+
+
+class ZipSetup(ModuleSetup):
+ MODULE = 'data01'
+
+ def tree_on_path(self, spec):
temp_dir = self.fixtures.enter_context(os_helper.temp_dir())
modules = pathlib.Path(temp_dir) / 'zipped modules.zip'
- src_path = pathlib.Path(__file__).parent.joinpath(self.ZIP_MODULE)
self.fixtures.enter_context(
- import_helper.DirsOnSysPath(str(zip_.make_zip_file(src_path, modules)))
+ import_helper.DirsOnSysPath(str(zip_.make_zip_file(spec, modules)))
)
- self.data = importlib.import_module(self.ZIP_MODULE)
+
+class DiskSetup(ModuleSetup):
+ MODULE = 'data01'
+
+ def tree_on_path(self, spec):
+ temp_dir = self.fixtures.enter_context(os_helper.temp_dir())
+ _path.build(spec, pathlib.Path(temp_dir))
+ self.fixtures.enter_context(import_helper.DirsOnSysPath(temp_dir))
-class ZipSetup(ZipSetupBase):
+class CommonTests(DiskSetup, CommonTestsBase):
pass
diff --git a/lib/importlib_resources/tests/zip.py b/lib/importlib_resources/tests/zip.py
index 962195a9..51ee5648 100644
--- a/lib/importlib_resources/tests/zip.py
+++ b/lib/importlib_resources/tests/zip.py
@@ -2,31 +2,25 @@
Generate zip test data files.
"""
-import contextlib
-import os
-import pathlib
import zipfile
import zipp
-def make_zip_file(src, dst):
+def make_zip_file(tree, dst):
"""
- Zip the files in src into a new zipfile at dst.
+ Zip the files in tree into a new zipfile at dst.
"""
with zipfile.ZipFile(dst, 'w') as zf:
- for src_path, rel in walk(src):
- dst_name = src.name / pathlib.PurePosixPath(rel.as_posix())
- zf.write(src_path, dst_name)
+ for name, contents in walk(tree):
+ zf.writestr(name, contents)
zipp.CompleteDirs.inject(zf)
return dst
-def walk(datapath):
- for dirpath, dirnames, filenames in os.walk(datapath):
- with contextlib.suppress(ValueError):
- dirnames.remove('__pycache__')
- for filename in filenames:
- res = pathlib.Path(dirpath) / filename
- rel = res.relative_to(datapath)
- yield res, rel
+def walk(tree, prefix=''):
+ for name, contents in tree.items():
+ if isinstance(contents, dict):
+ yield from walk(contents, prefix=f'{prefix}{name}/')
+ else:
+ yield f'{prefix}{name}', contents
diff --git a/lib/jwt/__init__.py b/lib/jwt/__init__.py
index b7a258d7..457a4e35 100644
--- a/lib/jwt/__init__.py
+++ b/lib/jwt/__init__.py
@@ -6,7 +6,7 @@ from .api_jws import (
register_algorithm,
unregister_algorithm,
)
-from .api_jwt import PyJWT, decode, encode
+from .api_jwt import PyJWT, decode, decode_complete, encode
from .exceptions import (
DecodeError,
ExpiredSignatureError,
@@ -27,7 +27,7 @@ from .exceptions import (
)
from .jwks_client import PyJWKClient
-__version__ = "2.9.0"
+__version__ = "2.10.1"
__title__ = "PyJWT"
__description__ = "JSON Web Token implementation in Python"
@@ -49,6 +49,7 @@ __all__ = [
"PyJWK",
"PyJWKSet",
"decode",
+ "decode_complete",
"encode",
"get_unverified_header",
"register_algorithm",
diff --git a/lib/jwt/algorithms.py b/lib/jwt/algorithms.py
index 9be50b20..ccb1500f 100644
--- a/lib/jwt/algorithms.py
+++ b/lib/jwt/algorithms.py
@@ -297,7 +297,7 @@ class HMACAlgorithm(Algorithm):
else:
raise ValueError
except ValueError:
- raise InvalidKeyError("Key is not valid JSON")
+ raise InvalidKeyError("Key is not valid JSON") from None
if obj.get("kty") != "oct":
raise InvalidKeyError("Not an HMAC key")
@@ -346,7 +346,9 @@ if has_crypto:
try:
return cast(RSAPublicKey, load_pem_public_key(key_bytes))
except (ValueError, UnsupportedAlgorithm):
- raise InvalidKeyError("Could not parse the provided public key.")
+ raise InvalidKeyError(
+ "Could not parse the provided public key."
+ ) from None
@overload
@staticmethod
@@ -409,10 +411,10 @@ if has_crypto:
else:
raise ValueError
except ValueError:
- raise InvalidKeyError("Key is not valid JSON")
+ raise InvalidKeyError("Key is not valid JSON") from None
if obj.get("kty") != "RSA":
- raise InvalidKeyError("Not an RSA key")
+ raise InvalidKeyError("Not an RSA key") from None
if "d" in obj and "e" in obj and "n" in obj:
# Private key
@@ -428,7 +430,7 @@ if has_crypto:
if any_props_found and not all(props_found):
raise InvalidKeyError(
"RSA key must include all parameters if any are present besides d"
- )
+ ) from None
public_numbers = RSAPublicNumbers(
from_base64url_uint(obj["e"]),
@@ -520,7 +522,7 @@ if has_crypto:
):
raise InvalidKeyError(
"Expecting a EllipticCurvePrivateKey/EllipticCurvePublicKey. Wrong key provided for ECDSA algorithms"
- )
+ ) from None
return crypto_key
@@ -581,13 +583,20 @@ if has_crypto:
obj: dict[str, Any] = {
"kty": "EC",
"crv": crv,
- "x": to_base64url_uint(public_numbers.x).decode(),
- "y": to_base64url_uint(public_numbers.y).decode(),
+ "x": to_base64url_uint(
+ public_numbers.x,
+ bit_length=key_obj.curve.key_size,
+ ).decode(),
+ "y": to_base64url_uint(
+ public_numbers.y,
+ bit_length=key_obj.curve.key_size,
+ ).decode(),
}
if isinstance(key_obj, EllipticCurvePrivateKey):
obj["d"] = to_base64url_uint(
- key_obj.private_numbers().private_value
+ key_obj.private_numbers().private_value,
+ bit_length=key_obj.curve.key_size,
).decode()
if as_dict:
@@ -605,13 +614,13 @@ if has_crypto:
else:
raise ValueError
except ValueError:
- raise InvalidKeyError("Key is not valid JSON")
+ raise InvalidKeyError("Key is not valid JSON") from None
if obj.get("kty") != "EC":
- raise InvalidKeyError("Not an Elliptic curve key")
+ raise InvalidKeyError("Not an Elliptic curve key") from None
if "x" not in obj or "y" not in obj:
- raise InvalidKeyError("Not an Elliptic curve key")
+ raise InvalidKeyError("Not an Elliptic curve key") from None
x = base64url_decode(obj.get("x"))
y = base64url_decode(obj.get("y"))
@@ -623,17 +632,23 @@ if has_crypto:
if len(x) == len(y) == 32:
curve_obj = SECP256R1()
else:
- raise InvalidKeyError("Coords should be 32 bytes for curve P-256")
+ raise InvalidKeyError(
+ "Coords should be 32 bytes for curve P-256"
+ ) from None
elif curve == "P-384":
if len(x) == len(y) == 48:
curve_obj = SECP384R1()
else:
- raise InvalidKeyError("Coords should be 48 bytes for curve P-384")
+ raise InvalidKeyError(
+ "Coords should be 48 bytes for curve P-384"
+ ) from None
elif curve == "P-521":
if len(x) == len(y) == 66:
curve_obj = SECP521R1()
else:
- raise InvalidKeyError("Coords should be 66 bytes for curve P-521")
+ raise InvalidKeyError(
+ "Coords should be 66 bytes for curve P-521"
+ ) from None
elif curve == "secp256k1":
if len(x) == len(y) == 32:
curve_obj = SECP256K1()
@@ -834,7 +849,7 @@ if has_crypto:
else:
raise ValueError
except ValueError:
- raise InvalidKeyError("Key is not valid JSON")
+ raise InvalidKeyError("Key is not valid JSON") from None
if obj.get("kty") != "OKP":
raise InvalidKeyError("Not an Octet Key Pair")
diff --git a/lib/jwt/api_jws.py b/lib/jwt/api_jws.py
index 5822ebf6..654ee0b7 100644
--- a/lib/jwt/api_jws.py
+++ b/lib/jwt/api_jws.py
@@ -3,6 +3,7 @@ from __future__ import annotations
import binascii
import json
import warnings
+from collections.abc import Sequence
from typing import TYPE_CHECKING, Any
from .algorithms import (
@@ -30,7 +31,7 @@ class PyJWS:
def __init__(
self,
- algorithms: list[str] | None = None,
+ algorithms: Sequence[str] | None = None,
options: dict[str, Any] | None = None,
) -> None:
self._algorithms = get_default_algorithms()
@@ -104,8 +105,8 @@ class PyJWS:
def encode(
self,
payload: bytes,
- key: AllowedPrivateKeys | str | bytes,
- algorithm: str | None = "HS256",
+ key: AllowedPrivateKeys | PyJWK | str | bytes,
+ algorithm: str | None = None,
headers: dict[str, Any] | None = None,
json_encoder: type[json.JSONEncoder] | None = None,
is_payload_detached: bool = False,
@@ -114,7 +115,13 @@ class PyJWS:
segments = []
# declare a new var to narrow the type for type checkers
- algorithm_: str = algorithm if algorithm is not None else "none"
+ if algorithm is None:
+ if isinstance(key, PyJWK):
+ algorithm_ = key.algorithm_name
+ else:
+ algorithm_ = "HS256"
+ else:
+ algorithm_ = algorithm
# Prefer headers values if present to function parameters.
if headers:
@@ -158,6 +165,8 @@ class PyJWS:
signing_input = b".".join(segments)
alg_obj = self.get_algorithm_by_name(algorithm_)
+ if isinstance(key, PyJWK):
+ key = key.key
key = alg_obj.prepare_key(key)
signature = alg_obj.sign(signing_input, key)
@@ -174,7 +183,7 @@ class PyJWS:
self,
jwt: str | bytes,
key: AllowedPublicKeys | PyJWK | str | bytes = "",
- algorithms: list[str] | None = None,
+ algorithms: Sequence[str] | None = None,
options: dict[str, Any] | None = None,
detached_payload: bytes | None = None,
**kwargs,
@@ -185,6 +194,7 @@ class PyJWS:
"and will be removed in pyjwt version 3. "
f"Unsupported kwargs: {tuple(kwargs.keys())}",
RemovedInPyjwt3Warning,
+ stacklevel=2,
)
if options is None:
options = {}
@@ -219,7 +229,7 @@ class PyJWS:
self,
jwt: str | bytes,
key: AllowedPublicKeys | PyJWK | str | bytes = "",
- algorithms: list[str] | None = None,
+ algorithms: Sequence[str] | None = None,
options: dict[str, Any] | None = None,
detached_payload: bytes | None = None,
**kwargs,
@@ -230,6 +240,7 @@ class PyJWS:
"and will be removed in pyjwt version 3. "
f"Unsupported kwargs: {tuple(kwargs.keys())}",
RemovedInPyjwt3Warning,
+ stacklevel=2,
)
decoded = self.decode_complete(
jwt, key, algorithms, options, detached_payload=detached_payload
@@ -291,14 +302,14 @@ class PyJWS:
header: dict[str, Any],
signature: bytes,
key: AllowedPublicKeys | PyJWK | str | bytes = "",
- algorithms: list[str] | None = None,
+ algorithms: Sequence[str] | None = None,
) -> None:
if algorithms is None and isinstance(key, PyJWK):
algorithms = [key.algorithm_name]
try:
alg = header["alg"]
except KeyError:
- raise InvalidAlgorithmError("Algorithm not specified")
+ raise InvalidAlgorithmError("Algorithm not specified") from None
if not alg or (algorithms is not None and alg not in algorithms):
raise InvalidAlgorithmError("The specified alg value is not allowed")
diff --git a/lib/jwt/api_jwt.py b/lib/jwt/api_jwt.py
index 7a07c336..3a201436 100644
--- a/lib/jwt/api_jwt.py
+++ b/lib/jwt/api_jwt.py
@@ -3,9 +3,9 @@ from __future__ import annotations
import json
import warnings
from calendar import timegm
-from collections.abc import Iterable
+from collections.abc import Iterable, Sequence
from datetime import datetime, timedelta, timezone
-from typing import TYPE_CHECKING, Any, List
+from typing import TYPE_CHECKING, Any
from . import api_jws
from .exceptions import (
@@ -15,6 +15,8 @@ from .exceptions import (
InvalidAudienceError,
InvalidIssuedAtError,
InvalidIssuerError,
+ InvalidJTIError,
+ InvalidSubjectError,
MissingRequiredClaimError,
)
from .warnings import RemovedInPyjwt3Warning
@@ -39,14 +41,16 @@ class PyJWT:
"verify_iat": True,
"verify_aud": True,
"verify_iss": True,
+ "verify_sub": True,
+ "verify_jti": True,
"require": [],
}
def encode(
self,
payload: dict[str, Any],
- key: AllowedPrivateKeys | str | bytes,
- algorithm: str | None = "HS256",
+ key: AllowedPrivateKeys | PyJWK | str | bytes,
+ algorithm: str | None = None,
headers: dict[str, Any] | None = None,
json_encoder: type[json.JSONEncoder] | None = None,
sort_headers: bool = True,
@@ -102,7 +106,7 @@ class PyJWT:
self,
jwt: str | bytes,
key: AllowedPublicKeys | PyJWK | str | bytes = "",
- algorithms: list[str] | None = None,
+ algorithms: Sequence[str] | None = None,
options: dict[str, Any] | None = None,
# deprecated arg, remove in pyjwt3
verify: bool | None = None,
@@ -111,7 +115,8 @@ class PyJWT:
# passthrough arguments to _validate_claims
# consider putting in options
audience: str | Iterable[str] | None = None,
- issuer: str | List[str] | None = None,
+ issuer: str | Sequence[str] | None = None,
+ subject: str | None = None,
leeway: float | timedelta = 0,
# kwargs
**kwargs: Any,
@@ -122,6 +127,7 @@ class PyJWT:
"and will be removed in pyjwt version 3. "
f"Unsupported kwargs: {tuple(kwargs.keys())}",
RemovedInPyjwt3Warning,
+ stacklevel=2,
)
options = dict(options or {}) # shallow-copy or initialize an empty dict
options.setdefault("verify_signature", True)
@@ -135,6 +141,7 @@ class PyJWT:
"The equivalent is setting `verify_signature` to False in the `options` dictionary. "
"This invocation has a mismatch between the kwarg and the option entry.",
category=DeprecationWarning,
+ stacklevel=2,
)
if not options["verify_signature"]:
@@ -143,11 +150,8 @@ class PyJWT:
options.setdefault("verify_iat", False)
options.setdefault("verify_aud", False)
options.setdefault("verify_iss", False)
-
- if options["verify_signature"] and not algorithms:
- raise DecodeError(
- 'It is required that you pass in a value for the "algorithms" argument when calling decode().'
- )
+ options.setdefault("verify_sub", False)
+ options.setdefault("verify_jti", False)
decoded = api_jws.decode_complete(
jwt,
@@ -161,7 +165,12 @@ class PyJWT:
merged_options = {**self.options, **options}
self._validate_claims(
- payload, merged_options, audience=audience, issuer=issuer, leeway=leeway
+ payload,
+ merged_options,
+ audience=audience,
+ issuer=issuer,
+ leeway=leeway,
+ subject=subject,
)
decoded["payload"] = payload
@@ -178,7 +187,7 @@ class PyJWT:
try:
payload = json.loads(decoded["payload"])
except ValueError as e:
- raise DecodeError(f"Invalid payload string: {e}")
+ raise DecodeError(f"Invalid payload string: {e}") from e
if not isinstance(payload, dict):
raise DecodeError("Invalid payload string: must be a json object")
return payload
@@ -187,7 +196,7 @@ class PyJWT:
self,
jwt: str | bytes,
key: AllowedPublicKeys | PyJWK | str | bytes = "",
- algorithms: list[str] | None = None,
+ algorithms: Sequence[str] | None = None,
options: dict[str, Any] | None = None,
# deprecated arg, remove in pyjwt3
verify: bool | None = None,
@@ -196,7 +205,8 @@ class PyJWT:
# passthrough arguments to _validate_claims
# consider putting in options
audience: str | Iterable[str] | None = None,
- issuer: str | List[str] | None = None,
+ subject: str | None = None,
+ issuer: str | Sequence[str] | None = None,
leeway: float | timedelta = 0,
# kwargs
**kwargs: Any,
@@ -207,6 +217,7 @@ class PyJWT:
"and will be removed in pyjwt version 3. "
f"Unsupported kwargs: {tuple(kwargs.keys())}",
RemovedInPyjwt3Warning,
+ stacklevel=2,
)
decoded = self.decode_complete(
jwt,
@@ -216,6 +227,7 @@ class PyJWT:
verify=verify,
detached_payload=detached_payload,
audience=audience,
+ subject=subject,
issuer=issuer,
leeway=leeway,
)
@@ -227,6 +239,7 @@ class PyJWT:
options: dict[str, Any],
audience=None,
issuer=None,
+ subject: str | None = None,
leeway: float | timedelta = 0,
) -> None:
if isinstance(leeway, timedelta):
@@ -256,6 +269,12 @@ class PyJWT:
payload, audience, strict=options.get("strict_aud", False)
)
+ if options["verify_sub"]:
+ self._validate_sub(payload, subject)
+
+ if options["verify_jti"]:
+ self._validate_jti(payload)
+
def _validate_required_claims(
self,
payload: dict[str, Any],
@@ -265,6 +284,39 @@ class PyJWT:
if payload.get(claim) is None:
raise MissingRequiredClaimError(claim)
+ def _validate_sub(self, payload: dict[str, Any], subject=None) -> None:
+ """
+ Checks whether "sub" if in the payload is valid ot not.
+ This is an Optional claim
+
+ :param payload(dict): The payload which needs to be validated
+ :param subject(str): The subject of the token
+ """
+
+ if "sub" not in payload:
+ return
+
+ if not isinstance(payload["sub"], str):
+ raise InvalidSubjectError("Subject must be a string")
+
+ if subject is not None:
+ if payload.get("sub") != subject:
+ raise InvalidSubjectError("Invalid subject")
+
+ def _validate_jti(self, payload: dict[str, Any]) -> None:
+ """
+ Checks whether "jti" if in the payload is valid ot not
+ This is an Optional claim
+
+ :param payload(dict): The payload which needs to be validated
+ """
+
+ if "jti" not in payload:
+ return
+
+ if not isinstance(payload.get("jti"), str):
+ raise InvalidJTIError("JWT ID must be a string")
+
def _validate_iat(
self,
payload: dict[str, Any],
@@ -274,7 +326,9 @@ class PyJWT:
try:
iat = int(payload["iat"])
except ValueError:
- raise InvalidIssuedAtError("Issued At claim (iat) must be an integer.")
+ raise InvalidIssuedAtError(
+ "Issued At claim (iat) must be an integer."
+ ) from None
if iat > (now + leeway):
raise ImmatureSignatureError("The token is not yet valid (iat)")
@@ -287,7 +341,7 @@ class PyJWT:
try:
nbf = int(payload["nbf"])
except ValueError:
- raise DecodeError("Not Before claim (nbf) must be an integer.")
+ raise DecodeError("Not Before claim (nbf) must be an integer.") from None
if nbf > (now + leeway):
raise ImmatureSignatureError("The token is not yet valid (nbf)")
@@ -301,7 +355,9 @@ class PyJWT:
try:
exp = int(payload["exp"])
except ValueError:
- raise DecodeError("Expiration Time claim (exp) must be an integer.")
+ raise DecodeError(
+ "Expiration Time claim (exp) must be an integer."
+ ) from None
if exp <= (now - leeway):
raise ExpiredSignatureError("Signature has expired")
@@ -363,11 +419,11 @@ class PyJWT:
if "iss" not in payload:
raise MissingRequiredClaimError("iss")
- if isinstance(issuer, list):
- if payload["iss"] not in issuer:
+ if isinstance(issuer, str):
+ if payload["iss"] != issuer:
raise InvalidIssuerError("Invalid issuer")
else:
- if payload["iss"] != issuer:
+ if payload["iss"] not in issuer:
raise InvalidIssuerError("Invalid issuer")
diff --git a/lib/jwt/exceptions.py b/lib/jwt/exceptions.py
index 0d985882..9b45ae48 100644
--- a/lib/jwt/exceptions.py
+++ b/lib/jwt/exceptions.py
@@ -72,3 +72,11 @@ class PyJWKClientError(PyJWTError):
class PyJWKClientConnectionError(PyJWKClientError):
pass
+
+
+class InvalidSubjectError(InvalidTokenError):
+ pass
+
+
+class InvalidJTIError(InvalidTokenError):
+ pass
diff --git a/lib/jwt/help.py b/lib/jwt/help.py
index 80b0ca56..8e1c2286 100644
--- a/lib/jwt/help.py
+++ b/lib/jwt/help.py
@@ -39,7 +39,10 @@ def info() -> Dict[str, Dict[str, str]]:
)
if pypy_version_info.releaselevel != "final":
implementation_version = "".join(
- [implementation_version, pypy_version_info.releaselevel]
+ [
+ implementation_version,
+ pypy_version_info.releaselevel,
+ ]
)
else:
implementation_version = "Unknown"
diff --git a/lib/jwt/jwks_client.py b/lib/jwt/jwks_client.py
index f19b10ac..9a8992ca 100644
--- a/lib/jwt/jwks_client.py
+++ b/lib/jwt/jwks_client.py
@@ -45,7 +45,9 @@ class PyJWKClient:
if cache_keys:
# Cache signing keys
# Ignore mypy (https://github.com/python/mypy/issues/2427)
- self.get_signing_key = lru_cache(maxsize=max_cached_keys)(self.get_signing_key) # type: ignore
+ self.get_signing_key = lru_cache(maxsize=max_cached_keys)(
+ self.get_signing_key
+ ) # type: ignore
def fetch_data(self) -> Any:
jwk_set: Any = None
@@ -58,7 +60,7 @@ class PyJWKClient:
except (URLError, TimeoutError) as e:
raise PyJWKClientConnectionError(
f'Fail to fetch data from the url, err: "{e}"'
- )
+ ) from e
else:
return jwk_set
finally:
diff --git a/lib/jwt/utils.py b/lib/jwt/utils.py
index d469139b..56e89bb7 100644
--- a/lib/jwt/utils.py
+++ b/lib/jwt/utils.py
@@ -1,7 +1,7 @@
import base64
import binascii
import re
-from typing import Union
+from typing import Optional, Union
try:
from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurve
@@ -37,11 +37,11 @@ def base64url_encode(input: bytes) -> bytes:
return base64.urlsafe_b64encode(input).replace(b"=", b"")
-def to_base64url_uint(val: int) -> bytes:
+def to_base64url_uint(val: int, *, bit_length: Optional[int] = None) -> bytes:
if val < 0:
raise ValueError("Must be a positive integer")
- int_bytes = bytes_from_int(val)
+ int_bytes = bytes_from_int(val, bit_length=bit_length)
if len(int_bytes) == 0:
int_bytes = b"\x00"
@@ -63,13 +63,10 @@ def bytes_to_number(string: bytes) -> int:
return int(binascii.b2a_hex(string), 16)
-def bytes_from_int(val: int) -> bytes:
- remaining = val
- byte_length = 0
-
- while remaining != 0:
- remaining >>= 8
- byte_length += 1
+def bytes_from_int(val: int, *, bit_length: Optional[int] = None) -> bytes:
+ if bit_length is None:
+ bit_length = val.bit_length()
+ byte_length = (bit_length + 7) // 8
return val.to_bytes(byte_length, "big", signed=False)
diff --git a/lib/mako/__init__.py b/lib/mako/__init__.py
index 0ac3dd68..d7223f7c 100644
--- a/lib/mako/__init__.py
+++ b/lib/mako/__init__.py
@@ -5,4 +5,4 @@
# the MIT License: http://www.opensource.org/licenses/mit-license.php
-__version__ = "1.3.5"
+__version__ = "1.3.6"
diff --git a/lib/mako/lexer.py b/lib/mako/lexer.py
index 9d1f5f30..b4a76a45 100644
--- a/lib/mako/lexer.py
+++ b/lib/mako/lexer.py
@@ -375,7 +375,7 @@ class Lexer:
|
(?=\${) # an expression
|
- (?=?[%&]) # a substitution or block or call start or end
+ (?=?%) # a substitution or block or call start or end
# - don't consume
|
(\\\r?\n) # an escaped newline - throw away
diff --git a/lib/markupsafe/__init__.py b/lib/markupsafe/__init__.py
index b40f24c6..fee8dc7a 100644
--- a/lib/markupsafe/__init__.py
+++ b/lib/markupsafe/__init__.py
@@ -1,29 +1,84 @@
-import functools
+from __future__ import annotations
+
+import collections.abc as cabc
import string
-import sys
import typing as t
+try:
+ from ._speedups import _escape_inner
+except ImportError:
+ from ._native import _escape_inner
+
if t.TYPE_CHECKING:
import typing_extensions as te
- class HasHTML(te.Protocol):
- def __html__(self) -> str:
- pass
- _P = te.ParamSpec("_P")
+class _HasHTML(t.Protocol):
+ def __html__(self, /) -> str: ...
-__version__ = "2.1.5"
+class _TPEscape(t.Protocol):
+ def __call__(self, s: t.Any, /) -> Markup: ...
-def _simple_escaping_wrapper(func: "t.Callable[_P, str]") -> "t.Callable[_P, Markup]":
- @functools.wraps(func)
- def wrapped(self: "Markup", *args: "_P.args", **kwargs: "_P.kwargs") -> "Markup":
- arg_list = _escape_argspec(list(args), enumerate(args), self.escape)
- _escape_argspec(kwargs, kwargs.items(), self.escape)
- return self.__class__(func(self, *arg_list, **kwargs)) # type: ignore[arg-type]
+def escape(s: t.Any, /) -> Markup:
+ """Replace the characters ``&``, ``<``, ``>``, ``'``, and ``"`` in
+ the string with HTML-safe sequences. Use this if you need to display
+ text that might contain such characters in HTML.
- return wrapped # type: ignore[return-value]
+ If the object has an ``__html__`` method, it is called and the
+ return value is assumed to already be safe for HTML.
+
+ :param s: An object to be converted to a string and escaped.
+ :return: A :class:`Markup` string with the escaped text.
+ """
+ # If the object is already a plain string, skip __html__ check and string
+ # conversion. This is the most common use case.
+ # Use type(s) instead of s.__class__ because a proxy object may be reporting
+ # the __class__ of the proxied value.
+ if type(s) is str:
+ return Markup(_escape_inner(s))
+
+ if hasattr(s, "__html__"):
+ return Markup(s.__html__())
+
+ return Markup(_escape_inner(str(s)))
+
+
+def escape_silent(s: t.Any | None, /) -> Markup:
+ """Like :func:`escape` but treats ``None`` as the empty string.
+ Useful with optional values, as otherwise you get the string
+ ``'None'`` when the value is ``None``.
+
+ >>> escape(None)
+ Markup('None')
+ >>> escape_silent(None)
+ Markup('')
+ """
+ if s is None:
+ return Markup()
+
+ return escape(s)
+
+
+def soft_str(s: t.Any, /) -> str:
+ """Convert an object to a string if it isn't already. This preserves
+ a :class:`Markup` string rather than converting it back to a basic
+ string, so it will still be marked as safe and won't be escaped
+ again.
+
+ >>> value = escape("")
+ >>> value
+ Markup('<User 1>')
+ >>> escape(str(value))
+ Markup('<User 1>')
+ >>> escape(soft_str(value))
+ Markup('<User 1>')
+ """
+ if not isinstance(s, str):
+ return str(s)
+
+ return s
class Markup(str):
@@ -65,82 +120,72 @@ class Markup(str):
__slots__ = ()
def __new__(
- cls, base: t.Any = "", encoding: t.Optional[str] = None, errors: str = "strict"
- ) -> "te.Self":
- if hasattr(base, "__html__"):
- base = base.__html__()
+ cls, object: t.Any = "", encoding: str | None = None, errors: str = "strict"
+ ) -> te.Self:
+ if hasattr(object, "__html__"):
+ object = object.__html__()
if encoding is None:
- return super().__new__(cls, base)
+ return super().__new__(cls, object)
- return super().__new__(cls, base, encoding, errors)
+ return super().__new__(cls, object, encoding, errors)
- def __html__(self) -> "te.Self":
+ def __html__(self, /) -> te.Self:
return self
- def __add__(self, other: t.Union[str, "HasHTML"]) -> "te.Self":
- if isinstance(other, str) or hasattr(other, "__html__"):
- return self.__class__(super().__add__(self.escape(other)))
+ def __add__(self, value: str | _HasHTML, /) -> te.Self:
+ if isinstance(value, str) or hasattr(value, "__html__"):
+ return self.__class__(super().__add__(self.escape(value)))
return NotImplemented
- def __radd__(self, other: t.Union[str, "HasHTML"]) -> "te.Self":
- if isinstance(other, str) or hasattr(other, "__html__"):
- return self.escape(other).__add__(self)
+ def __radd__(self, value: str | _HasHTML, /) -> te.Self:
+ if isinstance(value, str) or hasattr(value, "__html__"):
+ return self.escape(value).__add__(self)
return NotImplemented
- def __mul__(self, num: "te.SupportsIndex") -> "te.Self":
- if isinstance(num, int):
- return self.__class__(super().__mul__(num))
+ def __mul__(self, value: t.SupportsIndex, /) -> te.Self:
+ return self.__class__(super().__mul__(value))
- return NotImplemented
+ def __rmul__(self, value: t.SupportsIndex, /) -> te.Self:
+ return self.__class__(super().__mul__(value))
- __rmul__ = __mul__
-
- def __mod__(self, arg: t.Any) -> "te.Self":
- if isinstance(arg, tuple):
+ def __mod__(self, value: t.Any, /) -> te.Self:
+ if isinstance(value, tuple):
# a tuple of arguments, each wrapped
- arg = tuple(_MarkupEscapeHelper(x, self.escape) for x in arg)
- elif hasattr(type(arg), "__getitem__") and not isinstance(arg, str):
+ value = tuple(_MarkupEscapeHelper(x, self.escape) for x in value)
+ elif hasattr(type(value), "__getitem__") and not isinstance(value, str):
# a mapping of arguments, wrapped
- arg = _MarkupEscapeHelper(arg, self.escape)
+ value = _MarkupEscapeHelper(value, self.escape)
else:
# a single argument, wrapped with the helper and a tuple
- arg = (_MarkupEscapeHelper(arg, self.escape),)
+ value = (_MarkupEscapeHelper(value, self.escape),)
- return self.__class__(super().__mod__(arg))
+ return self.__class__(super().__mod__(value))
- def __repr__(self) -> str:
+ def __repr__(self, /) -> str:
return f"{self.__class__.__name__}({super().__repr__()})"
- def join(self, seq: t.Iterable[t.Union[str, "HasHTML"]]) -> "te.Self":
- return self.__class__(super().join(map(self.escape, seq)))
-
- join.__doc__ = str.join.__doc__
+ def join(self, iterable: cabc.Iterable[str | _HasHTML], /) -> te.Self:
+ return self.__class__(super().join(map(self.escape, iterable)))
def split( # type: ignore[override]
- self, sep: t.Optional[str] = None, maxsplit: int = -1
- ) -> t.List["te.Self"]:
+ self, /, sep: str | None = None, maxsplit: t.SupportsIndex = -1
+ ) -> list[te.Self]:
return [self.__class__(v) for v in super().split(sep, maxsplit)]
- split.__doc__ = str.split.__doc__
-
def rsplit( # type: ignore[override]
- self, sep: t.Optional[str] = None, maxsplit: int = -1
- ) -> t.List["te.Self"]:
+ self, /, sep: str | None = None, maxsplit: t.SupportsIndex = -1
+ ) -> list[te.Self]:
return [self.__class__(v) for v in super().rsplit(sep, maxsplit)]
- rsplit.__doc__ = str.rsplit.__doc__
-
def splitlines( # type: ignore[override]
- self, keepends: bool = False
- ) -> t.List["te.Self"]:
+ self, /, keepends: bool = False
+ ) -> list[te.Self]:
return [self.__class__(v) for v in super().splitlines(keepends)]
- splitlines.__doc__ = str.splitlines.__doc__
-
- def unescape(self) -> str:
+ def unescape(self, /) -> str:
"""Convert escaped markup back into a text string. This replaces
HTML entities with the characters they represent.
@@ -151,7 +196,7 @@ class Markup(str):
return unescape(str(self))
- def striptags(self) -> str:
+ def striptags(self, /) -> str:
""":meth:`unescape` the markup, remove tags, and normalize
whitespace to single spaces.
@@ -163,31 +208,17 @@ class Markup(str):
# Look for comments then tags separately. Otherwise, a comment that
# contains a tag would end early, leaving some of the comment behind.
- while True:
- # keep finding comment start marks
- start = value.find("", start)
-
- if end == -1:
+ if (end := value.find("-->", start)) == -1:
break
value = f"{value[:start]}{value[end + 3:]}"
# remove tags using the same method
- while True:
- start = value.find("<")
-
- if start == -1:
- break
-
- end = value.find(">", start)
-
- if end == -1:
+ while (start := value.find("<")) != -1:
+ if (end := value.find(">", start)) == -1:
break
value = f"{value[:start]}{value[end + 1:]}"
@@ -197,7 +228,7 @@ class Markup(str):
return self.__class__(value).unescape()
@classmethod
- def escape(cls, s: t.Any) -> "te.Self":
+ def escape(cls, s: t.Any, /) -> te.Self:
"""Escape a string. Calls :func:`escape` and ensures that for
subclasses the correct type is returned.
"""
@@ -208,49 +239,90 @@ class Markup(str):
return rv # type: ignore[return-value]
- __getitem__ = _simple_escaping_wrapper(str.__getitem__)
- capitalize = _simple_escaping_wrapper(str.capitalize)
- title = _simple_escaping_wrapper(str.title)
- lower = _simple_escaping_wrapper(str.lower)
- upper = _simple_escaping_wrapper(str.upper)
- replace = _simple_escaping_wrapper(str.replace)
- ljust = _simple_escaping_wrapper(str.ljust)
- rjust = _simple_escaping_wrapper(str.rjust)
- lstrip = _simple_escaping_wrapper(str.lstrip)
- rstrip = _simple_escaping_wrapper(str.rstrip)
- center = _simple_escaping_wrapper(str.center)
- strip = _simple_escaping_wrapper(str.strip)
- translate = _simple_escaping_wrapper(str.translate)
- expandtabs = _simple_escaping_wrapper(str.expandtabs)
- swapcase = _simple_escaping_wrapper(str.swapcase)
- zfill = _simple_escaping_wrapper(str.zfill)
- casefold = _simple_escaping_wrapper(str.casefold)
+ def __getitem__(self, key: t.SupportsIndex | slice, /) -> te.Self:
+ return self.__class__(super().__getitem__(key))
- if sys.version_info >= (3, 9):
- removeprefix = _simple_escaping_wrapper(str.removeprefix)
- removesuffix = _simple_escaping_wrapper(str.removesuffix)
+ def capitalize(self, /) -> te.Self:
+ return self.__class__(super().capitalize())
- def partition(self, sep: str) -> t.Tuple["te.Self", "te.Self", "te.Self"]:
- l, s, r = super().partition(self.escape(sep))
+ def title(self, /) -> te.Self:
+ return self.__class__(super().title())
+
+ def lower(self, /) -> te.Self:
+ return self.__class__(super().lower())
+
+ def upper(self, /) -> te.Self:
+ return self.__class__(super().upper())
+
+ def replace(self, old: str, new: str, count: t.SupportsIndex = -1, /) -> te.Self:
+ return self.__class__(super().replace(old, self.escape(new), count))
+
+ def ljust(self, width: t.SupportsIndex, fillchar: str = " ", /) -> te.Self:
+ return self.__class__(super().ljust(width, self.escape(fillchar)))
+
+ def rjust(self, width: t.SupportsIndex, fillchar: str = " ", /) -> te.Self:
+ return self.__class__(super().rjust(width, self.escape(fillchar)))
+
+ def lstrip(self, chars: str | None = None, /) -> te.Self:
+ return self.__class__(super().lstrip(chars))
+
+ def rstrip(self, chars: str | None = None, /) -> te.Self:
+ return self.__class__(super().rstrip(chars))
+
+ def center(self, width: t.SupportsIndex, fillchar: str = " ", /) -> te.Self:
+ return self.__class__(super().center(width, self.escape(fillchar)))
+
+ def strip(self, chars: str | None = None, /) -> te.Self:
+ return self.__class__(super().strip(chars))
+
+ def translate(
+ self,
+ table: cabc.Mapping[int, str | int | None], # type: ignore[override]
+ /,
+ ) -> str:
+ return self.__class__(super().translate(table))
+
+ def expandtabs(self, /, tabsize: t.SupportsIndex = 8) -> te.Self:
+ return self.__class__(super().expandtabs(tabsize))
+
+ def swapcase(self, /) -> te.Self:
+ return self.__class__(super().swapcase())
+
+ def zfill(self, width: t.SupportsIndex, /) -> te.Self:
+ return self.__class__(super().zfill(width))
+
+ def casefold(self, /) -> te.Self:
+ return self.__class__(super().casefold())
+
+ def removeprefix(self, prefix: str, /) -> te.Self:
+ return self.__class__(super().removeprefix(prefix))
+
+ def removesuffix(self, suffix: str) -> te.Self:
+ return self.__class__(super().removesuffix(suffix))
+
+ def partition(self, sep: str, /) -> tuple[te.Self, te.Self, te.Self]:
+ left, sep, right = super().partition(sep)
cls = self.__class__
- return cls(l), cls(s), cls(r)
+ return cls(left), cls(sep), cls(right)
- def rpartition(self, sep: str) -> t.Tuple["te.Self", "te.Self", "te.Self"]:
- l, s, r = super().rpartition(self.escape(sep))
+ def rpartition(self, sep: str, /) -> tuple[te.Self, te.Self, te.Self]:
+ left, sep, right = super().rpartition(sep)
cls = self.__class__
- return cls(l), cls(s), cls(r)
+ return cls(left), cls(sep), cls(right)
- def format(self, *args: t.Any, **kwargs: t.Any) -> "te.Self":
+ def format(self, *args: t.Any, **kwargs: t.Any) -> te.Self:
formatter = EscapeFormatter(self.escape)
return self.__class__(formatter.vformat(self, args, kwargs))
- def format_map( # type: ignore[override]
- self, map: t.Mapping[str, t.Any]
- ) -> "te.Self":
+ def format_map(
+ self,
+ mapping: cabc.Mapping[str, t.Any], # type: ignore[override]
+ /,
+ ) -> te.Self:
formatter = EscapeFormatter(self.escape)
- return self.__class__(formatter.vformat(self, (), map))
+ return self.__class__(formatter.vformat(self, (), mapping))
- def __html_format__(self, format_spec: str) -> "te.Self":
+ def __html_format__(self, format_spec: str, /) -> te.Self:
if format_spec:
raise ValueError("Unsupported format specification for Markup.")
@@ -260,8 +332,8 @@ class Markup(str):
class EscapeFormatter(string.Formatter):
__slots__ = ("escape",)
- def __init__(self, escape: t.Callable[[t.Any], Markup]) -> None:
- self.escape = escape
+ def __init__(self, escape: _TPEscape) -> None:
+ self.escape: _TPEscape = escape
super().__init__()
def format_field(self, value: t.Any, format_spec: str) -> str:
@@ -278,55 +350,46 @@ class EscapeFormatter(string.Formatter):
else:
# We need to make sure the format spec is str here as
# otherwise the wrong callback methods are invoked.
- rv = string.Formatter.format_field(self, value, str(format_spec))
+ rv = super().format_field(value, str(format_spec))
return str(self.escape(rv))
-_ListOrDict = t.TypeVar("_ListOrDict", list, dict)
-
-
-def _escape_argspec(
- obj: _ListOrDict, iterable: t.Iterable[t.Any], escape: t.Callable[[t.Any], Markup]
-) -> _ListOrDict:
- """Helper for various string-wrapped functions."""
- for key, value in iterable:
- if isinstance(value, str) or hasattr(value, "__html__"):
- obj[key] = escape(value)
-
- return obj
-
-
class _MarkupEscapeHelper:
"""Helper for :meth:`Markup.__mod__`."""
__slots__ = ("obj", "escape")
- def __init__(self, obj: t.Any, escape: t.Callable[[t.Any], Markup]) -> None:
- self.obj = obj
- self.escape = escape
+ def __init__(self, obj: t.Any, escape: _TPEscape) -> None:
+ self.obj: t.Any = obj
+ self.escape: _TPEscape = escape
- def __getitem__(self, item: t.Any) -> "te.Self":
- return self.__class__(self.obj[item], self.escape)
+ def __getitem__(self, key: t.Any, /) -> te.Self:
+ return self.__class__(self.obj[key], self.escape)
- def __str__(self) -> str:
+ def __str__(self, /) -> str:
return str(self.escape(self.obj))
- def __repr__(self) -> str:
+ def __repr__(self, /) -> str:
return str(self.escape(repr(self.obj)))
- def __int__(self) -> int:
+ def __int__(self, /) -> int:
return int(self.obj)
- def __float__(self) -> float:
+ def __float__(self, /) -> float:
return float(self.obj)
-# circular import
-try:
- from ._speedups import escape as escape
- from ._speedups import escape_silent as escape_silent
- from ._speedups import soft_str as soft_str
-except ImportError:
- from ._native import escape as escape
- from ._native import escape_silent as escape_silent # noqa: F401
- from ._native import soft_str as soft_str # noqa: F401
+def __getattr__(name: str) -> t.Any:
+ if name == "__version__":
+ import importlib.metadata
+ import warnings
+
+ warnings.warn(
+ "The '__version__' attribute is deprecated and will be removed in"
+ " MarkupSafe 3.1. Use feature detection, or"
+ ' `importlib.metadata.version("markupsafe")`, instead.',
+ stacklevel=2,
+ )
+ return importlib.metadata.version("markupsafe")
+
+ raise AttributeError(name)
diff --git a/lib/markupsafe/_native.py b/lib/markupsafe/_native.py
index 8117b271..088b3bca 100644
--- a/lib/markupsafe/_native.py
+++ b/lib/markupsafe/_native.py
@@ -1,63 +1,8 @@
-import typing as t
-
-from . import Markup
-
-
-def escape(s: t.Any) -> Markup:
- """Replace the characters ``&``, ``<``, ``>``, ``'``, and ``"`` in
- the string with HTML-safe sequences. Use this if you need to display
- text that might contain such characters in HTML.
-
- If the object has an ``__html__`` method, it is called and the
- return value is assumed to already be safe for HTML.
-
- :param s: An object to be converted to a string and escaped.
- :return: A :class:`Markup` string with the escaped text.
- """
- if hasattr(s, "__html__"):
- return Markup(s.__html__())
-
- return Markup(
- str(s)
- .replace("&", "&")
+def _escape_inner(s: str, /) -> str:
+ return (
+ s.replace("&", "&")
.replace(">", ">")
.replace("<", "<")
.replace("'", "'")
.replace('"', """)
)
-
-
-def escape_silent(s: t.Optional[t.Any]) -> Markup:
- """Like :func:`escape` but treats ``None`` as the empty string.
- Useful with optional values, as otherwise you get the string
- ``'None'`` when the value is ``None``.
-
- >>> escape(None)
- Markup('None')
- >>> escape_silent(None)
- Markup('')
- """
- if s is None:
- return Markup()
-
- return escape(s)
-
-
-def soft_str(s: t.Any) -> str:
- """Convert an object to a string if it isn't already. This preserves
- a :class:`Markup` string rather than converting it back to a basic
- string, so it will still be marked as safe and won't be escaped
- again.
-
- >>> value = escape("")
- >>> value
- Markup('<User 1>')
- >>> escape(str(value))
- Markup('<User 1>')
- >>> escape(soft_str(value))
- Markup('<User 1>')
- """
- if not isinstance(s, str):
- return str(s)
-
- return s
diff --git a/lib/markupsafe/_speedups.c b/lib/markupsafe/_speedups.c
index 3c463fb8..09dd57ca 100644
--- a/lib/markupsafe/_speedups.c
+++ b/lib/markupsafe/_speedups.c
@@ -1,22 +1,5 @@
#include
-static PyObject* markup;
-
-static int
-init_constants(void)
-{
- PyObject *module;
-
- /* import markup type so that we can mark the return value */
- module = PyImport_ImportModule("markupsafe");
- if (!module)
- return 0;
- markup = PyObject_GetAttrString(module, "Markup");
- Py_DECREF(module);
-
- return 1;
-}
-
#define GET_DELTA(inp, inp_end, delta) \
while (inp < inp_end) { \
switch (*inp++) { \
@@ -166,135 +149,29 @@ escape_unicode_kind4(PyUnicodeObject *in)
}
static PyObject*
-escape_unicode(PyUnicodeObject *in)
+escape_unicode(PyObject *self, PyObject *s)
{
- if (PyUnicode_READY(in))
+ if (!PyUnicode_Check(s))
return NULL;
- switch (PyUnicode_KIND(in)) {
+ // This check is no longer needed in Python 3.12.
+ if (PyUnicode_READY(s))
+ return NULL;
+
+ switch (PyUnicode_KIND(s)) {
case PyUnicode_1BYTE_KIND:
- return escape_unicode_kind1(in);
+ return escape_unicode_kind1((PyUnicodeObject*) s);
case PyUnicode_2BYTE_KIND:
- return escape_unicode_kind2(in);
+ return escape_unicode_kind2((PyUnicodeObject*) s);
case PyUnicode_4BYTE_KIND:
- return escape_unicode_kind4(in);
+ return escape_unicode_kind4((PyUnicodeObject*) s);
}
assert(0); /* shouldn't happen */
return NULL;
}
-static PyObject*
-escape(PyObject *self, PyObject *text)
-{
- static PyObject *id_html;
- PyObject *s = NULL, *rv = NULL, *html;
-
- if (id_html == NULL) {
- id_html = PyUnicode_InternFromString("__html__");
- if (id_html == NULL) {
- return NULL;
- }
- }
-
- /* we don't have to escape integers, bools or floats */
- if (PyLong_CheckExact(text) ||
- PyFloat_CheckExact(text) || PyBool_Check(text) ||
- text == Py_None)
- return PyObject_CallFunctionObjArgs(markup, text, NULL);
-
- /* if the object has an __html__ method that performs the escaping */
- html = PyObject_GetAttr(text ,id_html);
- if (html) {
- s = PyObject_CallObject(html, NULL);
- Py_DECREF(html);
- if (s == NULL) {
- return NULL;
- }
- /* Convert to Markup object */
- rv = PyObject_CallFunctionObjArgs(markup, (PyObject*)s, NULL);
- Py_DECREF(s);
- return rv;
- }
-
- /* otherwise make the object unicode if it isn't, then escape */
- PyErr_Clear();
- if (!PyUnicode_Check(text)) {
- PyObject *unicode = PyObject_Str(text);
- if (!unicode)
- return NULL;
- s = escape_unicode((PyUnicodeObject*)unicode);
- Py_DECREF(unicode);
- }
- else
- s = escape_unicode((PyUnicodeObject*)text);
-
- /* convert the unicode string into a markup object. */
- rv = PyObject_CallFunctionObjArgs(markup, (PyObject*)s, NULL);
- Py_DECREF(s);
- return rv;
-}
-
-
-static PyObject*
-escape_silent(PyObject *self, PyObject *text)
-{
- if (text != Py_None)
- return escape(self, text);
- return PyObject_CallFunctionObjArgs(markup, NULL);
-}
-
-
-static PyObject*
-soft_str(PyObject *self, PyObject *s)
-{
- if (!PyUnicode_Check(s))
- return PyObject_Str(s);
- Py_INCREF(s);
- return s;
-}
-
-
static PyMethodDef module_methods[] = {
- {
- "escape",
- (PyCFunction)escape,
- METH_O,
- "Replace the characters ``&``, ``<``, ``>``, ``'``, and ``\"`` in"
- " the string with HTML-safe sequences. Use this if you need to display"
- " text that might contain such characters in HTML.\n\n"
- "If the object has an ``__html__`` method, it is called and the"
- " return value is assumed to already be safe for HTML.\n\n"
- ":param s: An object to be converted to a string and escaped.\n"
- ":return: A :class:`Markup` string with the escaped text.\n"
- },
- {
- "escape_silent",
- (PyCFunction)escape_silent,
- METH_O,
- "Like :func:`escape` but treats ``None`` as the empty string."
- " Useful with optional values, as otherwise you get the string"
- " ``'None'`` when the value is ``None``.\n\n"
- ">>> escape(None)\n"
- "Markup('None')\n"
- ">>> escape_silent(None)\n"
- "Markup('')\n"
- },
- {
- "soft_str",
- (PyCFunction)soft_str,
- METH_O,
- "Convert an object to a string if it isn't already. This preserves"
- " a :class:`Markup` string rather than converting it back to a basic"
- " string, so it will still be marked as safe and won't be escaped"
- " again.\n\n"
- ">>> value = escape(\"\")\n"
- ">>> value\n"
- "Markup('<User 1>')\n"
- ">>> escape(str(value))\n"
- "Markup('<User 1>')\n"
- ">>> escape(soft_str(value))\n"
- "Markup('<User 1>')\n"
- },
+ {"_escape_inner", (PyCFunction)escape_unicode, METH_O, NULL},
{NULL, NULL, 0, NULL} /* Sentinel */
};
@@ -313,8 +190,15 @@ static struct PyModuleDef module_definition = {
PyMODINIT_FUNC
PyInit__speedups(void)
{
- if (!init_constants())
- return NULL;
+ PyObject *m = PyModule_Create(&module_definition);
- return PyModule_Create(&module_definition);
+ if (m == NULL) {
+ return NULL;
+ }
+
+ #ifdef Py_GIL_DISABLED
+ PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED);
+ #endif
+
+ return m;
}
diff --git a/lib/markupsafe/_speedups.pyi b/lib/markupsafe/_speedups.pyi
index f673240f..8c888585 100644
--- a/lib/markupsafe/_speedups.pyi
+++ b/lib/markupsafe/_speedups.pyi
@@ -1,9 +1 @@
-from typing import Any
-from typing import Optional
-
-from . import Markup
-
-def escape(s: Any) -> Markup: ...
-def escape_silent(s: Optional[Any]) -> Markup: ...
-def soft_str(s: Any) -> str: ...
-def soft_unicode(s: Any) -> str: ...
+def _escape_inner(s: str, /) -> str: ...
diff --git a/lib/packaging/__init__.py b/lib/packaging/__init__.py
index 9ba41d83..d79f73c5 100644
--- a/lib/packaging/__init__.py
+++ b/lib/packaging/__init__.py
@@ -6,10 +6,10 @@ __title__ = "packaging"
__summary__ = "Core utilities for Python packages"
__uri__ = "https://github.com/pypa/packaging"
-__version__ = "24.1"
+__version__ = "24.2"
__author__ = "Donald Stufft and individual contributors"
__email__ = "donald@stufft.io"
__license__ = "BSD-2-Clause or Apache-2.0"
-__copyright__ = "2014 %s" % __author__
+__copyright__ = f"2014 {__author__}"
diff --git a/lib/packaging/_elffile.py b/lib/packaging/_elffile.py
index f7a02180..25f4282c 100644
--- a/lib/packaging/_elffile.py
+++ b/lib/packaging/_elffile.py
@@ -48,8 +48,8 @@ class ELFFile:
try:
ident = self._read("16B")
- except struct.error:
- raise ELFInvalid("unable to parse identification")
+ except struct.error as e:
+ raise ELFInvalid("unable to parse identification") from e
magic = bytes(ident[:4])
if magic != b"\x7fELF":
raise ELFInvalid(f"invalid magic: {magic!r}")
@@ -67,11 +67,11 @@ class ELFFile:
(2, 1): ("HHIQQQIHHH", ">IIQQQQQQ", (0, 2, 5)), # 64-bit MSB.
}[(self.capacity, self.encoding)]
- except KeyError:
+ except KeyError as e:
raise ELFInvalid(
f"unrecognized capacity ({self.capacity}) or "
f"encoding ({self.encoding})"
- )
+ ) from e
try:
(
diff --git a/lib/packaging/_manylinux.py b/lib/packaging/_manylinux.py
index 08f651fb..61339a6f 100644
--- a/lib/packaging/_manylinux.py
+++ b/lib/packaging/_manylinux.py
@@ -164,6 +164,7 @@ def _parse_glibc_version(version_str: str) -> tuple[int, int]:
f"Expected glibc version with 2 components major.minor,"
f" got: {version_str}",
RuntimeWarning,
+ stacklevel=2,
)
return -1, -1
return int(m.group("major")), int(m.group("minor"))
diff --git a/lib/packaging/licenses/__init__.py b/lib/packaging/licenses/__init__.py
new file mode 100644
index 00000000..569156d6
--- /dev/null
+++ b/lib/packaging/licenses/__init__.py
@@ -0,0 +1,145 @@
+#######################################################################################
+#
+# Adapted from:
+# https://github.com/pypa/hatch/blob/5352e44/backend/src/hatchling/licenses/parse.py
+#
+# MIT License
+#
+# Copyright (c) 2017-present Ofek Lev
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy of this
+# software and associated documentation files (the "Software"), to deal in the Software
+# without restriction, including without limitation the rights to use, copy, modify,
+# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be included in all copies
+# or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+#
+# With additional allowance of arbitrary `LicenseRef-` identifiers, not just
+# `LicenseRef-Public-Domain` and `LicenseRef-Proprietary`.
+#
+#######################################################################################
+from __future__ import annotations
+
+import re
+from typing import NewType, cast
+
+from packaging.licenses._spdx import EXCEPTIONS, LICENSES
+
+__all__ = [
+ "NormalizedLicenseExpression",
+ "InvalidLicenseExpression",
+ "canonicalize_license_expression",
+]
+
+license_ref_allowed = re.compile("^[A-Za-z0-9.-]*$")
+
+NormalizedLicenseExpression = NewType("NormalizedLicenseExpression", str)
+
+
+class InvalidLicenseExpression(ValueError):
+ """Raised when a license-expression string is invalid
+
+ >>> canonicalize_license_expression("invalid")
+ Traceback (most recent call last):
+ ...
+ packaging.licenses.InvalidLicenseExpression: Invalid license expression: 'invalid'
+ """
+
+
+def canonicalize_license_expression(
+ raw_license_expression: str,
+) -> NormalizedLicenseExpression:
+ if not raw_license_expression:
+ message = f"Invalid license expression: {raw_license_expression!r}"
+ raise InvalidLicenseExpression(message)
+
+ # Pad any parentheses so tokenization can be achieved by merely splitting on
+ # whitespace.
+ license_expression = raw_license_expression.replace("(", " ( ").replace(")", " ) ")
+ licenseref_prefix = "LicenseRef-"
+ license_refs = {
+ ref.lower(): "LicenseRef-" + ref[len(licenseref_prefix) :]
+ for ref in license_expression.split()
+ if ref.lower().startswith(licenseref_prefix.lower())
+ }
+
+ # Normalize to lower case so we can look up licenses/exceptions
+ # and so boolean operators are Python-compatible.
+ license_expression = license_expression.lower()
+
+ tokens = license_expression.split()
+
+ # Rather than implementing boolean logic, we create an expression that Python can
+ # parse. Everything that is not involved with the grammar itself is treated as
+ # `False` and the expression should evaluate as such.
+ python_tokens = []
+ for token in tokens:
+ if token not in {"or", "and", "with", "(", ")"}:
+ python_tokens.append("False")
+ elif token == "with":
+ python_tokens.append("or")
+ elif token == "(" and python_tokens and python_tokens[-1] not in {"or", "and"}:
+ message = f"Invalid license expression: {raw_license_expression!r}"
+ raise InvalidLicenseExpression(message)
+ else:
+ python_tokens.append(token)
+
+ python_expression = " ".join(python_tokens)
+ try:
+ invalid = eval(python_expression, globals(), locals())
+ except Exception:
+ invalid = True
+
+ if invalid is not False:
+ message = f"Invalid license expression: {raw_license_expression!r}"
+ raise InvalidLicenseExpression(message) from None
+
+ # Take a final pass to check for unknown licenses/exceptions.
+ normalized_tokens = []
+ for token in tokens:
+ if token in {"or", "and", "with", "(", ")"}:
+ normalized_tokens.append(token.upper())
+ continue
+
+ if normalized_tokens and normalized_tokens[-1] == "WITH":
+ if token not in EXCEPTIONS:
+ message = f"Unknown license exception: {token!r}"
+ raise InvalidLicenseExpression(message)
+
+ normalized_tokens.append(EXCEPTIONS[token]["id"])
+ else:
+ if token.endswith("+"):
+ final_token = token[:-1]
+ suffix = "+"
+ else:
+ final_token = token
+ suffix = ""
+
+ if final_token.startswith("licenseref-"):
+ if not license_ref_allowed.match(final_token):
+ message = f"Invalid licenseref: {final_token!r}"
+ raise InvalidLicenseExpression(message)
+ normalized_tokens.append(license_refs[final_token] + suffix)
+ else:
+ if final_token not in LICENSES:
+ message = f"Unknown license: {final_token!r}"
+ raise InvalidLicenseExpression(message)
+ normalized_tokens.append(LICENSES[final_token]["id"] + suffix)
+
+ normalized_expression = " ".join(normalized_tokens)
+
+ return cast(
+ NormalizedLicenseExpression,
+ normalized_expression.replace("( ", "(").replace(" )", ")"),
+ )
diff --git a/lib/packaging/licenses/_spdx.py b/lib/packaging/licenses/_spdx.py
new file mode 100644
index 00000000..eac22276
--- /dev/null
+++ b/lib/packaging/licenses/_spdx.py
@@ -0,0 +1,759 @@
+
+from __future__ import annotations
+
+from typing import TypedDict
+
+class SPDXLicense(TypedDict):
+ id: str
+ deprecated: bool
+
+class SPDXException(TypedDict):
+ id: str
+ deprecated: bool
+
+
+VERSION = '3.25.0'
+
+LICENSES: dict[str, SPDXLicense] = {
+ '0bsd': {'id': '0BSD', 'deprecated': False},
+ '3d-slicer-1.0': {'id': '3D-Slicer-1.0', 'deprecated': False},
+ 'aal': {'id': 'AAL', 'deprecated': False},
+ 'abstyles': {'id': 'Abstyles', 'deprecated': False},
+ 'adacore-doc': {'id': 'AdaCore-doc', 'deprecated': False},
+ 'adobe-2006': {'id': 'Adobe-2006', 'deprecated': False},
+ 'adobe-display-postscript': {'id': 'Adobe-Display-PostScript', 'deprecated': False},
+ 'adobe-glyph': {'id': 'Adobe-Glyph', 'deprecated': False},
+ 'adobe-utopia': {'id': 'Adobe-Utopia', 'deprecated': False},
+ 'adsl': {'id': 'ADSL', 'deprecated': False},
+ 'afl-1.1': {'id': 'AFL-1.1', 'deprecated': False},
+ 'afl-1.2': {'id': 'AFL-1.2', 'deprecated': False},
+ 'afl-2.0': {'id': 'AFL-2.0', 'deprecated': False},
+ 'afl-2.1': {'id': 'AFL-2.1', 'deprecated': False},
+ 'afl-3.0': {'id': 'AFL-3.0', 'deprecated': False},
+ 'afmparse': {'id': 'Afmparse', 'deprecated': False},
+ 'agpl-1.0': {'id': 'AGPL-1.0', 'deprecated': True},
+ 'agpl-1.0-only': {'id': 'AGPL-1.0-only', 'deprecated': False},
+ 'agpl-1.0-or-later': {'id': 'AGPL-1.0-or-later', 'deprecated': False},
+ 'agpl-3.0': {'id': 'AGPL-3.0', 'deprecated': True},
+ 'agpl-3.0-only': {'id': 'AGPL-3.0-only', 'deprecated': False},
+ 'agpl-3.0-or-later': {'id': 'AGPL-3.0-or-later', 'deprecated': False},
+ 'aladdin': {'id': 'Aladdin', 'deprecated': False},
+ 'amd-newlib': {'id': 'AMD-newlib', 'deprecated': False},
+ 'amdplpa': {'id': 'AMDPLPA', 'deprecated': False},
+ 'aml': {'id': 'AML', 'deprecated': False},
+ 'aml-glslang': {'id': 'AML-glslang', 'deprecated': False},
+ 'ampas': {'id': 'AMPAS', 'deprecated': False},
+ 'antlr-pd': {'id': 'ANTLR-PD', 'deprecated': False},
+ 'antlr-pd-fallback': {'id': 'ANTLR-PD-fallback', 'deprecated': False},
+ 'any-osi': {'id': 'any-OSI', 'deprecated': False},
+ 'apache-1.0': {'id': 'Apache-1.0', 'deprecated': False},
+ 'apache-1.1': {'id': 'Apache-1.1', 'deprecated': False},
+ 'apache-2.0': {'id': 'Apache-2.0', 'deprecated': False},
+ 'apafml': {'id': 'APAFML', 'deprecated': False},
+ 'apl-1.0': {'id': 'APL-1.0', 'deprecated': False},
+ 'app-s2p': {'id': 'App-s2p', 'deprecated': False},
+ 'apsl-1.0': {'id': 'APSL-1.0', 'deprecated': False},
+ 'apsl-1.1': {'id': 'APSL-1.1', 'deprecated': False},
+ 'apsl-1.2': {'id': 'APSL-1.2', 'deprecated': False},
+ 'apsl-2.0': {'id': 'APSL-2.0', 'deprecated': False},
+ 'arphic-1999': {'id': 'Arphic-1999', 'deprecated': False},
+ 'artistic-1.0': {'id': 'Artistic-1.0', 'deprecated': False},
+ 'artistic-1.0-cl8': {'id': 'Artistic-1.0-cl8', 'deprecated': False},
+ 'artistic-1.0-perl': {'id': 'Artistic-1.0-Perl', 'deprecated': False},
+ 'artistic-2.0': {'id': 'Artistic-2.0', 'deprecated': False},
+ 'aswf-digital-assets-1.0': {'id': 'ASWF-Digital-Assets-1.0', 'deprecated': False},
+ 'aswf-digital-assets-1.1': {'id': 'ASWF-Digital-Assets-1.1', 'deprecated': False},
+ 'baekmuk': {'id': 'Baekmuk', 'deprecated': False},
+ 'bahyph': {'id': 'Bahyph', 'deprecated': False},
+ 'barr': {'id': 'Barr', 'deprecated': False},
+ 'bcrypt-solar-designer': {'id': 'bcrypt-Solar-Designer', 'deprecated': False},
+ 'beerware': {'id': 'Beerware', 'deprecated': False},
+ 'bitstream-charter': {'id': 'Bitstream-Charter', 'deprecated': False},
+ 'bitstream-vera': {'id': 'Bitstream-Vera', 'deprecated': False},
+ 'bittorrent-1.0': {'id': 'BitTorrent-1.0', 'deprecated': False},
+ 'bittorrent-1.1': {'id': 'BitTorrent-1.1', 'deprecated': False},
+ 'blessing': {'id': 'blessing', 'deprecated': False},
+ 'blueoak-1.0.0': {'id': 'BlueOak-1.0.0', 'deprecated': False},
+ 'boehm-gc': {'id': 'Boehm-GC', 'deprecated': False},
+ 'borceux': {'id': 'Borceux', 'deprecated': False},
+ 'brian-gladman-2-clause': {'id': 'Brian-Gladman-2-Clause', 'deprecated': False},
+ 'brian-gladman-3-clause': {'id': 'Brian-Gladman-3-Clause', 'deprecated': False},
+ 'bsd-1-clause': {'id': 'BSD-1-Clause', 'deprecated': False},
+ 'bsd-2-clause': {'id': 'BSD-2-Clause', 'deprecated': False},
+ 'bsd-2-clause-darwin': {'id': 'BSD-2-Clause-Darwin', 'deprecated': False},
+ 'bsd-2-clause-first-lines': {'id': 'BSD-2-Clause-first-lines', 'deprecated': False},
+ 'bsd-2-clause-freebsd': {'id': 'BSD-2-Clause-FreeBSD', 'deprecated': True},
+ 'bsd-2-clause-netbsd': {'id': 'BSD-2-Clause-NetBSD', 'deprecated': True},
+ 'bsd-2-clause-patent': {'id': 'BSD-2-Clause-Patent', 'deprecated': False},
+ 'bsd-2-clause-views': {'id': 'BSD-2-Clause-Views', 'deprecated': False},
+ 'bsd-3-clause': {'id': 'BSD-3-Clause', 'deprecated': False},
+ 'bsd-3-clause-acpica': {'id': 'BSD-3-Clause-acpica', 'deprecated': False},
+ 'bsd-3-clause-attribution': {'id': 'BSD-3-Clause-Attribution', 'deprecated': False},
+ 'bsd-3-clause-clear': {'id': 'BSD-3-Clause-Clear', 'deprecated': False},
+ 'bsd-3-clause-flex': {'id': 'BSD-3-Clause-flex', 'deprecated': False},
+ 'bsd-3-clause-hp': {'id': 'BSD-3-Clause-HP', 'deprecated': False},
+ 'bsd-3-clause-lbnl': {'id': 'BSD-3-Clause-LBNL', 'deprecated': False},
+ 'bsd-3-clause-modification': {'id': 'BSD-3-Clause-Modification', 'deprecated': False},
+ 'bsd-3-clause-no-military-license': {'id': 'BSD-3-Clause-No-Military-License', 'deprecated': False},
+ 'bsd-3-clause-no-nuclear-license': {'id': 'BSD-3-Clause-No-Nuclear-License', 'deprecated': False},
+ 'bsd-3-clause-no-nuclear-license-2014': {'id': 'BSD-3-Clause-No-Nuclear-License-2014', 'deprecated': False},
+ 'bsd-3-clause-no-nuclear-warranty': {'id': 'BSD-3-Clause-No-Nuclear-Warranty', 'deprecated': False},
+ 'bsd-3-clause-open-mpi': {'id': 'BSD-3-Clause-Open-MPI', 'deprecated': False},
+ 'bsd-3-clause-sun': {'id': 'BSD-3-Clause-Sun', 'deprecated': False},
+ 'bsd-4-clause': {'id': 'BSD-4-Clause', 'deprecated': False},
+ 'bsd-4-clause-shortened': {'id': 'BSD-4-Clause-Shortened', 'deprecated': False},
+ 'bsd-4-clause-uc': {'id': 'BSD-4-Clause-UC', 'deprecated': False},
+ 'bsd-4.3reno': {'id': 'BSD-4.3RENO', 'deprecated': False},
+ 'bsd-4.3tahoe': {'id': 'BSD-4.3TAHOE', 'deprecated': False},
+ 'bsd-advertising-acknowledgement': {'id': 'BSD-Advertising-Acknowledgement', 'deprecated': False},
+ 'bsd-attribution-hpnd-disclaimer': {'id': 'BSD-Attribution-HPND-disclaimer', 'deprecated': False},
+ 'bsd-inferno-nettverk': {'id': 'BSD-Inferno-Nettverk', 'deprecated': False},
+ 'bsd-protection': {'id': 'BSD-Protection', 'deprecated': False},
+ 'bsd-source-beginning-file': {'id': 'BSD-Source-beginning-file', 'deprecated': False},
+ 'bsd-source-code': {'id': 'BSD-Source-Code', 'deprecated': False},
+ 'bsd-systemics': {'id': 'BSD-Systemics', 'deprecated': False},
+ 'bsd-systemics-w3works': {'id': 'BSD-Systemics-W3Works', 'deprecated': False},
+ 'bsl-1.0': {'id': 'BSL-1.0', 'deprecated': False},
+ 'busl-1.1': {'id': 'BUSL-1.1', 'deprecated': False},
+ 'bzip2-1.0.5': {'id': 'bzip2-1.0.5', 'deprecated': True},
+ 'bzip2-1.0.6': {'id': 'bzip2-1.0.6', 'deprecated': False},
+ 'c-uda-1.0': {'id': 'C-UDA-1.0', 'deprecated': False},
+ 'cal-1.0': {'id': 'CAL-1.0', 'deprecated': False},
+ 'cal-1.0-combined-work-exception': {'id': 'CAL-1.0-Combined-Work-Exception', 'deprecated': False},
+ 'caldera': {'id': 'Caldera', 'deprecated': False},
+ 'caldera-no-preamble': {'id': 'Caldera-no-preamble', 'deprecated': False},
+ 'catharon': {'id': 'Catharon', 'deprecated': False},
+ 'catosl-1.1': {'id': 'CATOSL-1.1', 'deprecated': False},
+ 'cc-by-1.0': {'id': 'CC-BY-1.0', 'deprecated': False},
+ 'cc-by-2.0': {'id': 'CC-BY-2.0', 'deprecated': False},
+ 'cc-by-2.5': {'id': 'CC-BY-2.5', 'deprecated': False},
+ 'cc-by-2.5-au': {'id': 'CC-BY-2.5-AU', 'deprecated': False},
+ 'cc-by-3.0': {'id': 'CC-BY-3.0', 'deprecated': False},
+ 'cc-by-3.0-at': {'id': 'CC-BY-3.0-AT', 'deprecated': False},
+ 'cc-by-3.0-au': {'id': 'CC-BY-3.0-AU', 'deprecated': False},
+ 'cc-by-3.0-de': {'id': 'CC-BY-3.0-DE', 'deprecated': False},
+ 'cc-by-3.0-igo': {'id': 'CC-BY-3.0-IGO', 'deprecated': False},
+ 'cc-by-3.0-nl': {'id': 'CC-BY-3.0-NL', 'deprecated': False},
+ 'cc-by-3.0-us': {'id': 'CC-BY-3.0-US', 'deprecated': False},
+ 'cc-by-4.0': {'id': 'CC-BY-4.0', 'deprecated': False},
+ 'cc-by-nc-1.0': {'id': 'CC-BY-NC-1.0', 'deprecated': False},
+ 'cc-by-nc-2.0': {'id': 'CC-BY-NC-2.0', 'deprecated': False},
+ 'cc-by-nc-2.5': {'id': 'CC-BY-NC-2.5', 'deprecated': False},
+ 'cc-by-nc-3.0': {'id': 'CC-BY-NC-3.0', 'deprecated': False},
+ 'cc-by-nc-3.0-de': {'id': 'CC-BY-NC-3.0-DE', 'deprecated': False},
+ 'cc-by-nc-4.0': {'id': 'CC-BY-NC-4.0', 'deprecated': False},
+ 'cc-by-nc-nd-1.0': {'id': 'CC-BY-NC-ND-1.0', 'deprecated': False},
+ 'cc-by-nc-nd-2.0': {'id': 'CC-BY-NC-ND-2.0', 'deprecated': False},
+ 'cc-by-nc-nd-2.5': {'id': 'CC-BY-NC-ND-2.5', 'deprecated': False},
+ 'cc-by-nc-nd-3.0': {'id': 'CC-BY-NC-ND-3.0', 'deprecated': False},
+ 'cc-by-nc-nd-3.0-de': {'id': 'CC-BY-NC-ND-3.0-DE', 'deprecated': False},
+ 'cc-by-nc-nd-3.0-igo': {'id': 'CC-BY-NC-ND-3.0-IGO', 'deprecated': False},
+ 'cc-by-nc-nd-4.0': {'id': 'CC-BY-NC-ND-4.0', 'deprecated': False},
+ 'cc-by-nc-sa-1.0': {'id': 'CC-BY-NC-SA-1.0', 'deprecated': False},
+ 'cc-by-nc-sa-2.0': {'id': 'CC-BY-NC-SA-2.0', 'deprecated': False},
+ 'cc-by-nc-sa-2.0-de': {'id': 'CC-BY-NC-SA-2.0-DE', 'deprecated': False},
+ 'cc-by-nc-sa-2.0-fr': {'id': 'CC-BY-NC-SA-2.0-FR', 'deprecated': False},
+ 'cc-by-nc-sa-2.0-uk': {'id': 'CC-BY-NC-SA-2.0-UK', 'deprecated': False},
+ 'cc-by-nc-sa-2.5': {'id': 'CC-BY-NC-SA-2.5', 'deprecated': False},
+ 'cc-by-nc-sa-3.0': {'id': 'CC-BY-NC-SA-3.0', 'deprecated': False},
+ 'cc-by-nc-sa-3.0-de': {'id': 'CC-BY-NC-SA-3.0-DE', 'deprecated': False},
+ 'cc-by-nc-sa-3.0-igo': {'id': 'CC-BY-NC-SA-3.0-IGO', 'deprecated': False},
+ 'cc-by-nc-sa-4.0': {'id': 'CC-BY-NC-SA-4.0', 'deprecated': False},
+ 'cc-by-nd-1.0': {'id': 'CC-BY-ND-1.0', 'deprecated': False},
+ 'cc-by-nd-2.0': {'id': 'CC-BY-ND-2.0', 'deprecated': False},
+ 'cc-by-nd-2.5': {'id': 'CC-BY-ND-2.5', 'deprecated': False},
+ 'cc-by-nd-3.0': {'id': 'CC-BY-ND-3.0', 'deprecated': False},
+ 'cc-by-nd-3.0-de': {'id': 'CC-BY-ND-3.0-DE', 'deprecated': False},
+ 'cc-by-nd-4.0': {'id': 'CC-BY-ND-4.0', 'deprecated': False},
+ 'cc-by-sa-1.0': {'id': 'CC-BY-SA-1.0', 'deprecated': False},
+ 'cc-by-sa-2.0': {'id': 'CC-BY-SA-2.0', 'deprecated': False},
+ 'cc-by-sa-2.0-uk': {'id': 'CC-BY-SA-2.0-UK', 'deprecated': False},
+ 'cc-by-sa-2.1-jp': {'id': 'CC-BY-SA-2.1-JP', 'deprecated': False},
+ 'cc-by-sa-2.5': {'id': 'CC-BY-SA-2.5', 'deprecated': False},
+ 'cc-by-sa-3.0': {'id': 'CC-BY-SA-3.0', 'deprecated': False},
+ 'cc-by-sa-3.0-at': {'id': 'CC-BY-SA-3.0-AT', 'deprecated': False},
+ 'cc-by-sa-3.0-de': {'id': 'CC-BY-SA-3.0-DE', 'deprecated': False},
+ 'cc-by-sa-3.0-igo': {'id': 'CC-BY-SA-3.0-IGO', 'deprecated': False},
+ 'cc-by-sa-4.0': {'id': 'CC-BY-SA-4.0', 'deprecated': False},
+ 'cc-pddc': {'id': 'CC-PDDC', 'deprecated': False},
+ 'cc0-1.0': {'id': 'CC0-1.0', 'deprecated': False},
+ 'cddl-1.0': {'id': 'CDDL-1.0', 'deprecated': False},
+ 'cddl-1.1': {'id': 'CDDL-1.1', 'deprecated': False},
+ 'cdl-1.0': {'id': 'CDL-1.0', 'deprecated': False},
+ 'cdla-permissive-1.0': {'id': 'CDLA-Permissive-1.0', 'deprecated': False},
+ 'cdla-permissive-2.0': {'id': 'CDLA-Permissive-2.0', 'deprecated': False},
+ 'cdla-sharing-1.0': {'id': 'CDLA-Sharing-1.0', 'deprecated': False},
+ 'cecill-1.0': {'id': 'CECILL-1.0', 'deprecated': False},
+ 'cecill-1.1': {'id': 'CECILL-1.1', 'deprecated': False},
+ 'cecill-2.0': {'id': 'CECILL-2.0', 'deprecated': False},
+ 'cecill-2.1': {'id': 'CECILL-2.1', 'deprecated': False},
+ 'cecill-b': {'id': 'CECILL-B', 'deprecated': False},
+ 'cecill-c': {'id': 'CECILL-C', 'deprecated': False},
+ 'cern-ohl-1.1': {'id': 'CERN-OHL-1.1', 'deprecated': False},
+ 'cern-ohl-1.2': {'id': 'CERN-OHL-1.2', 'deprecated': False},
+ 'cern-ohl-p-2.0': {'id': 'CERN-OHL-P-2.0', 'deprecated': False},
+ 'cern-ohl-s-2.0': {'id': 'CERN-OHL-S-2.0', 'deprecated': False},
+ 'cern-ohl-w-2.0': {'id': 'CERN-OHL-W-2.0', 'deprecated': False},
+ 'cfitsio': {'id': 'CFITSIO', 'deprecated': False},
+ 'check-cvs': {'id': 'check-cvs', 'deprecated': False},
+ 'checkmk': {'id': 'checkmk', 'deprecated': False},
+ 'clartistic': {'id': 'ClArtistic', 'deprecated': False},
+ 'clips': {'id': 'Clips', 'deprecated': False},
+ 'cmu-mach': {'id': 'CMU-Mach', 'deprecated': False},
+ 'cmu-mach-nodoc': {'id': 'CMU-Mach-nodoc', 'deprecated': False},
+ 'cnri-jython': {'id': 'CNRI-Jython', 'deprecated': False},
+ 'cnri-python': {'id': 'CNRI-Python', 'deprecated': False},
+ 'cnri-python-gpl-compatible': {'id': 'CNRI-Python-GPL-Compatible', 'deprecated': False},
+ 'coil-1.0': {'id': 'COIL-1.0', 'deprecated': False},
+ 'community-spec-1.0': {'id': 'Community-Spec-1.0', 'deprecated': False},
+ 'condor-1.1': {'id': 'Condor-1.1', 'deprecated': False},
+ 'copyleft-next-0.3.0': {'id': 'copyleft-next-0.3.0', 'deprecated': False},
+ 'copyleft-next-0.3.1': {'id': 'copyleft-next-0.3.1', 'deprecated': False},
+ 'cornell-lossless-jpeg': {'id': 'Cornell-Lossless-JPEG', 'deprecated': False},
+ 'cpal-1.0': {'id': 'CPAL-1.0', 'deprecated': False},
+ 'cpl-1.0': {'id': 'CPL-1.0', 'deprecated': False},
+ 'cpol-1.02': {'id': 'CPOL-1.02', 'deprecated': False},
+ 'cronyx': {'id': 'Cronyx', 'deprecated': False},
+ 'crossword': {'id': 'Crossword', 'deprecated': False},
+ 'crystalstacker': {'id': 'CrystalStacker', 'deprecated': False},
+ 'cua-opl-1.0': {'id': 'CUA-OPL-1.0', 'deprecated': False},
+ 'cube': {'id': 'Cube', 'deprecated': False},
+ 'curl': {'id': 'curl', 'deprecated': False},
+ 'cve-tou': {'id': 'cve-tou', 'deprecated': False},
+ 'd-fsl-1.0': {'id': 'D-FSL-1.0', 'deprecated': False},
+ 'dec-3-clause': {'id': 'DEC-3-Clause', 'deprecated': False},
+ 'diffmark': {'id': 'diffmark', 'deprecated': False},
+ 'dl-de-by-2.0': {'id': 'DL-DE-BY-2.0', 'deprecated': False},
+ 'dl-de-zero-2.0': {'id': 'DL-DE-ZERO-2.0', 'deprecated': False},
+ 'doc': {'id': 'DOC', 'deprecated': False},
+ 'docbook-schema': {'id': 'DocBook-Schema', 'deprecated': False},
+ 'docbook-xml': {'id': 'DocBook-XML', 'deprecated': False},
+ 'dotseqn': {'id': 'Dotseqn', 'deprecated': False},
+ 'drl-1.0': {'id': 'DRL-1.0', 'deprecated': False},
+ 'drl-1.1': {'id': 'DRL-1.1', 'deprecated': False},
+ 'dsdp': {'id': 'DSDP', 'deprecated': False},
+ 'dtoa': {'id': 'dtoa', 'deprecated': False},
+ 'dvipdfm': {'id': 'dvipdfm', 'deprecated': False},
+ 'ecl-1.0': {'id': 'ECL-1.0', 'deprecated': False},
+ 'ecl-2.0': {'id': 'ECL-2.0', 'deprecated': False},
+ 'ecos-2.0': {'id': 'eCos-2.0', 'deprecated': True},
+ 'efl-1.0': {'id': 'EFL-1.0', 'deprecated': False},
+ 'efl-2.0': {'id': 'EFL-2.0', 'deprecated': False},
+ 'egenix': {'id': 'eGenix', 'deprecated': False},
+ 'elastic-2.0': {'id': 'Elastic-2.0', 'deprecated': False},
+ 'entessa': {'id': 'Entessa', 'deprecated': False},
+ 'epics': {'id': 'EPICS', 'deprecated': False},
+ 'epl-1.0': {'id': 'EPL-1.0', 'deprecated': False},
+ 'epl-2.0': {'id': 'EPL-2.0', 'deprecated': False},
+ 'erlpl-1.1': {'id': 'ErlPL-1.1', 'deprecated': False},
+ 'etalab-2.0': {'id': 'etalab-2.0', 'deprecated': False},
+ 'eudatagrid': {'id': 'EUDatagrid', 'deprecated': False},
+ 'eupl-1.0': {'id': 'EUPL-1.0', 'deprecated': False},
+ 'eupl-1.1': {'id': 'EUPL-1.1', 'deprecated': False},
+ 'eupl-1.2': {'id': 'EUPL-1.2', 'deprecated': False},
+ 'eurosym': {'id': 'Eurosym', 'deprecated': False},
+ 'fair': {'id': 'Fair', 'deprecated': False},
+ 'fbm': {'id': 'FBM', 'deprecated': False},
+ 'fdk-aac': {'id': 'FDK-AAC', 'deprecated': False},
+ 'ferguson-twofish': {'id': 'Ferguson-Twofish', 'deprecated': False},
+ 'frameworx-1.0': {'id': 'Frameworx-1.0', 'deprecated': False},
+ 'freebsd-doc': {'id': 'FreeBSD-DOC', 'deprecated': False},
+ 'freeimage': {'id': 'FreeImage', 'deprecated': False},
+ 'fsfap': {'id': 'FSFAP', 'deprecated': False},
+ 'fsfap-no-warranty-disclaimer': {'id': 'FSFAP-no-warranty-disclaimer', 'deprecated': False},
+ 'fsful': {'id': 'FSFUL', 'deprecated': False},
+ 'fsfullr': {'id': 'FSFULLR', 'deprecated': False},
+ 'fsfullrwd': {'id': 'FSFULLRWD', 'deprecated': False},
+ 'ftl': {'id': 'FTL', 'deprecated': False},
+ 'furuseth': {'id': 'Furuseth', 'deprecated': False},
+ 'fwlw': {'id': 'fwlw', 'deprecated': False},
+ 'gcr-docs': {'id': 'GCR-docs', 'deprecated': False},
+ 'gd': {'id': 'GD', 'deprecated': False},
+ 'gfdl-1.1': {'id': 'GFDL-1.1', 'deprecated': True},
+ 'gfdl-1.1-invariants-only': {'id': 'GFDL-1.1-invariants-only', 'deprecated': False},
+ 'gfdl-1.1-invariants-or-later': {'id': 'GFDL-1.1-invariants-or-later', 'deprecated': False},
+ 'gfdl-1.1-no-invariants-only': {'id': 'GFDL-1.1-no-invariants-only', 'deprecated': False},
+ 'gfdl-1.1-no-invariants-or-later': {'id': 'GFDL-1.1-no-invariants-or-later', 'deprecated': False},
+ 'gfdl-1.1-only': {'id': 'GFDL-1.1-only', 'deprecated': False},
+ 'gfdl-1.1-or-later': {'id': 'GFDL-1.1-or-later', 'deprecated': False},
+ 'gfdl-1.2': {'id': 'GFDL-1.2', 'deprecated': True},
+ 'gfdl-1.2-invariants-only': {'id': 'GFDL-1.2-invariants-only', 'deprecated': False},
+ 'gfdl-1.2-invariants-or-later': {'id': 'GFDL-1.2-invariants-or-later', 'deprecated': False},
+ 'gfdl-1.2-no-invariants-only': {'id': 'GFDL-1.2-no-invariants-only', 'deprecated': False},
+ 'gfdl-1.2-no-invariants-or-later': {'id': 'GFDL-1.2-no-invariants-or-later', 'deprecated': False},
+ 'gfdl-1.2-only': {'id': 'GFDL-1.2-only', 'deprecated': False},
+ 'gfdl-1.2-or-later': {'id': 'GFDL-1.2-or-later', 'deprecated': False},
+ 'gfdl-1.3': {'id': 'GFDL-1.3', 'deprecated': True},
+ 'gfdl-1.3-invariants-only': {'id': 'GFDL-1.3-invariants-only', 'deprecated': False},
+ 'gfdl-1.3-invariants-or-later': {'id': 'GFDL-1.3-invariants-or-later', 'deprecated': False},
+ 'gfdl-1.3-no-invariants-only': {'id': 'GFDL-1.3-no-invariants-only', 'deprecated': False},
+ 'gfdl-1.3-no-invariants-or-later': {'id': 'GFDL-1.3-no-invariants-or-later', 'deprecated': False},
+ 'gfdl-1.3-only': {'id': 'GFDL-1.3-only', 'deprecated': False},
+ 'gfdl-1.3-or-later': {'id': 'GFDL-1.3-or-later', 'deprecated': False},
+ 'giftware': {'id': 'Giftware', 'deprecated': False},
+ 'gl2ps': {'id': 'GL2PS', 'deprecated': False},
+ 'glide': {'id': 'Glide', 'deprecated': False},
+ 'glulxe': {'id': 'Glulxe', 'deprecated': False},
+ 'glwtpl': {'id': 'GLWTPL', 'deprecated': False},
+ 'gnuplot': {'id': 'gnuplot', 'deprecated': False},
+ 'gpl-1.0': {'id': 'GPL-1.0', 'deprecated': True},
+ 'gpl-1.0+': {'id': 'GPL-1.0+', 'deprecated': True},
+ 'gpl-1.0-only': {'id': 'GPL-1.0-only', 'deprecated': False},
+ 'gpl-1.0-or-later': {'id': 'GPL-1.0-or-later', 'deprecated': False},
+ 'gpl-2.0': {'id': 'GPL-2.0', 'deprecated': True},
+ 'gpl-2.0+': {'id': 'GPL-2.0+', 'deprecated': True},
+ 'gpl-2.0-only': {'id': 'GPL-2.0-only', 'deprecated': False},
+ 'gpl-2.0-or-later': {'id': 'GPL-2.0-or-later', 'deprecated': False},
+ 'gpl-2.0-with-autoconf-exception': {'id': 'GPL-2.0-with-autoconf-exception', 'deprecated': True},
+ 'gpl-2.0-with-bison-exception': {'id': 'GPL-2.0-with-bison-exception', 'deprecated': True},
+ 'gpl-2.0-with-classpath-exception': {'id': 'GPL-2.0-with-classpath-exception', 'deprecated': True},
+ 'gpl-2.0-with-font-exception': {'id': 'GPL-2.0-with-font-exception', 'deprecated': True},
+ 'gpl-2.0-with-gcc-exception': {'id': 'GPL-2.0-with-GCC-exception', 'deprecated': True},
+ 'gpl-3.0': {'id': 'GPL-3.0', 'deprecated': True},
+ 'gpl-3.0+': {'id': 'GPL-3.0+', 'deprecated': True},
+ 'gpl-3.0-only': {'id': 'GPL-3.0-only', 'deprecated': False},
+ 'gpl-3.0-or-later': {'id': 'GPL-3.0-or-later', 'deprecated': False},
+ 'gpl-3.0-with-autoconf-exception': {'id': 'GPL-3.0-with-autoconf-exception', 'deprecated': True},
+ 'gpl-3.0-with-gcc-exception': {'id': 'GPL-3.0-with-GCC-exception', 'deprecated': True},
+ 'graphics-gems': {'id': 'Graphics-Gems', 'deprecated': False},
+ 'gsoap-1.3b': {'id': 'gSOAP-1.3b', 'deprecated': False},
+ 'gtkbook': {'id': 'gtkbook', 'deprecated': False},
+ 'gutmann': {'id': 'Gutmann', 'deprecated': False},
+ 'haskellreport': {'id': 'HaskellReport', 'deprecated': False},
+ 'hdparm': {'id': 'hdparm', 'deprecated': False},
+ 'hidapi': {'id': 'HIDAPI', 'deprecated': False},
+ 'hippocratic-2.1': {'id': 'Hippocratic-2.1', 'deprecated': False},
+ 'hp-1986': {'id': 'HP-1986', 'deprecated': False},
+ 'hp-1989': {'id': 'HP-1989', 'deprecated': False},
+ 'hpnd': {'id': 'HPND', 'deprecated': False},
+ 'hpnd-dec': {'id': 'HPND-DEC', 'deprecated': False},
+ 'hpnd-doc': {'id': 'HPND-doc', 'deprecated': False},
+ 'hpnd-doc-sell': {'id': 'HPND-doc-sell', 'deprecated': False},
+ 'hpnd-export-us': {'id': 'HPND-export-US', 'deprecated': False},
+ 'hpnd-export-us-acknowledgement': {'id': 'HPND-export-US-acknowledgement', 'deprecated': False},
+ 'hpnd-export-us-modify': {'id': 'HPND-export-US-modify', 'deprecated': False},
+ 'hpnd-export2-us': {'id': 'HPND-export2-US', 'deprecated': False},
+ 'hpnd-fenneberg-livingston': {'id': 'HPND-Fenneberg-Livingston', 'deprecated': False},
+ 'hpnd-inria-imag': {'id': 'HPND-INRIA-IMAG', 'deprecated': False},
+ 'hpnd-intel': {'id': 'HPND-Intel', 'deprecated': False},
+ 'hpnd-kevlin-henney': {'id': 'HPND-Kevlin-Henney', 'deprecated': False},
+ 'hpnd-markus-kuhn': {'id': 'HPND-Markus-Kuhn', 'deprecated': False},
+ 'hpnd-merchantability-variant': {'id': 'HPND-merchantability-variant', 'deprecated': False},
+ 'hpnd-mit-disclaimer': {'id': 'HPND-MIT-disclaimer', 'deprecated': False},
+ 'hpnd-netrek': {'id': 'HPND-Netrek', 'deprecated': False},
+ 'hpnd-pbmplus': {'id': 'HPND-Pbmplus', 'deprecated': False},
+ 'hpnd-sell-mit-disclaimer-xserver': {'id': 'HPND-sell-MIT-disclaimer-xserver', 'deprecated': False},
+ 'hpnd-sell-regexpr': {'id': 'HPND-sell-regexpr', 'deprecated': False},
+ 'hpnd-sell-variant': {'id': 'HPND-sell-variant', 'deprecated': False},
+ 'hpnd-sell-variant-mit-disclaimer': {'id': 'HPND-sell-variant-MIT-disclaimer', 'deprecated': False},
+ 'hpnd-sell-variant-mit-disclaimer-rev': {'id': 'HPND-sell-variant-MIT-disclaimer-rev', 'deprecated': False},
+ 'hpnd-uc': {'id': 'HPND-UC', 'deprecated': False},
+ 'hpnd-uc-export-us': {'id': 'HPND-UC-export-US', 'deprecated': False},
+ 'htmltidy': {'id': 'HTMLTIDY', 'deprecated': False},
+ 'ibm-pibs': {'id': 'IBM-pibs', 'deprecated': False},
+ 'icu': {'id': 'ICU', 'deprecated': False},
+ 'iec-code-components-eula': {'id': 'IEC-Code-Components-EULA', 'deprecated': False},
+ 'ijg': {'id': 'IJG', 'deprecated': False},
+ 'ijg-short': {'id': 'IJG-short', 'deprecated': False},
+ 'imagemagick': {'id': 'ImageMagick', 'deprecated': False},
+ 'imatix': {'id': 'iMatix', 'deprecated': False},
+ 'imlib2': {'id': 'Imlib2', 'deprecated': False},
+ 'info-zip': {'id': 'Info-ZIP', 'deprecated': False},
+ 'inner-net-2.0': {'id': 'Inner-Net-2.0', 'deprecated': False},
+ 'intel': {'id': 'Intel', 'deprecated': False},
+ 'intel-acpi': {'id': 'Intel-ACPI', 'deprecated': False},
+ 'interbase-1.0': {'id': 'Interbase-1.0', 'deprecated': False},
+ 'ipa': {'id': 'IPA', 'deprecated': False},
+ 'ipl-1.0': {'id': 'IPL-1.0', 'deprecated': False},
+ 'isc': {'id': 'ISC', 'deprecated': False},
+ 'isc-veillard': {'id': 'ISC-Veillard', 'deprecated': False},
+ 'jam': {'id': 'Jam', 'deprecated': False},
+ 'jasper-2.0': {'id': 'JasPer-2.0', 'deprecated': False},
+ 'jpl-image': {'id': 'JPL-image', 'deprecated': False},
+ 'jpnic': {'id': 'JPNIC', 'deprecated': False},
+ 'json': {'id': 'JSON', 'deprecated': False},
+ 'kastrup': {'id': 'Kastrup', 'deprecated': False},
+ 'kazlib': {'id': 'Kazlib', 'deprecated': False},
+ 'knuth-ctan': {'id': 'Knuth-CTAN', 'deprecated': False},
+ 'lal-1.2': {'id': 'LAL-1.2', 'deprecated': False},
+ 'lal-1.3': {'id': 'LAL-1.3', 'deprecated': False},
+ 'latex2e': {'id': 'Latex2e', 'deprecated': False},
+ 'latex2e-translated-notice': {'id': 'Latex2e-translated-notice', 'deprecated': False},
+ 'leptonica': {'id': 'Leptonica', 'deprecated': False},
+ 'lgpl-2.0': {'id': 'LGPL-2.0', 'deprecated': True},
+ 'lgpl-2.0+': {'id': 'LGPL-2.0+', 'deprecated': True},
+ 'lgpl-2.0-only': {'id': 'LGPL-2.0-only', 'deprecated': False},
+ 'lgpl-2.0-or-later': {'id': 'LGPL-2.0-or-later', 'deprecated': False},
+ 'lgpl-2.1': {'id': 'LGPL-2.1', 'deprecated': True},
+ 'lgpl-2.1+': {'id': 'LGPL-2.1+', 'deprecated': True},
+ 'lgpl-2.1-only': {'id': 'LGPL-2.1-only', 'deprecated': False},
+ 'lgpl-2.1-or-later': {'id': 'LGPL-2.1-or-later', 'deprecated': False},
+ 'lgpl-3.0': {'id': 'LGPL-3.0', 'deprecated': True},
+ 'lgpl-3.0+': {'id': 'LGPL-3.0+', 'deprecated': True},
+ 'lgpl-3.0-only': {'id': 'LGPL-3.0-only', 'deprecated': False},
+ 'lgpl-3.0-or-later': {'id': 'LGPL-3.0-or-later', 'deprecated': False},
+ 'lgpllr': {'id': 'LGPLLR', 'deprecated': False},
+ 'libpng': {'id': 'Libpng', 'deprecated': False},
+ 'libpng-2.0': {'id': 'libpng-2.0', 'deprecated': False},
+ 'libselinux-1.0': {'id': 'libselinux-1.0', 'deprecated': False},
+ 'libtiff': {'id': 'libtiff', 'deprecated': False},
+ 'libutil-david-nugent': {'id': 'libutil-David-Nugent', 'deprecated': False},
+ 'liliq-p-1.1': {'id': 'LiLiQ-P-1.1', 'deprecated': False},
+ 'liliq-r-1.1': {'id': 'LiLiQ-R-1.1', 'deprecated': False},
+ 'liliq-rplus-1.1': {'id': 'LiLiQ-Rplus-1.1', 'deprecated': False},
+ 'linux-man-pages-1-para': {'id': 'Linux-man-pages-1-para', 'deprecated': False},
+ 'linux-man-pages-copyleft': {'id': 'Linux-man-pages-copyleft', 'deprecated': False},
+ 'linux-man-pages-copyleft-2-para': {'id': 'Linux-man-pages-copyleft-2-para', 'deprecated': False},
+ 'linux-man-pages-copyleft-var': {'id': 'Linux-man-pages-copyleft-var', 'deprecated': False},
+ 'linux-openib': {'id': 'Linux-OpenIB', 'deprecated': False},
+ 'loop': {'id': 'LOOP', 'deprecated': False},
+ 'lpd-document': {'id': 'LPD-document', 'deprecated': False},
+ 'lpl-1.0': {'id': 'LPL-1.0', 'deprecated': False},
+ 'lpl-1.02': {'id': 'LPL-1.02', 'deprecated': False},
+ 'lppl-1.0': {'id': 'LPPL-1.0', 'deprecated': False},
+ 'lppl-1.1': {'id': 'LPPL-1.1', 'deprecated': False},
+ 'lppl-1.2': {'id': 'LPPL-1.2', 'deprecated': False},
+ 'lppl-1.3a': {'id': 'LPPL-1.3a', 'deprecated': False},
+ 'lppl-1.3c': {'id': 'LPPL-1.3c', 'deprecated': False},
+ 'lsof': {'id': 'lsof', 'deprecated': False},
+ 'lucida-bitmap-fonts': {'id': 'Lucida-Bitmap-Fonts', 'deprecated': False},
+ 'lzma-sdk-9.11-to-9.20': {'id': 'LZMA-SDK-9.11-to-9.20', 'deprecated': False},
+ 'lzma-sdk-9.22': {'id': 'LZMA-SDK-9.22', 'deprecated': False},
+ 'mackerras-3-clause': {'id': 'Mackerras-3-Clause', 'deprecated': False},
+ 'mackerras-3-clause-acknowledgment': {'id': 'Mackerras-3-Clause-acknowledgment', 'deprecated': False},
+ 'magaz': {'id': 'magaz', 'deprecated': False},
+ 'mailprio': {'id': 'mailprio', 'deprecated': False},
+ 'makeindex': {'id': 'MakeIndex', 'deprecated': False},
+ 'martin-birgmeier': {'id': 'Martin-Birgmeier', 'deprecated': False},
+ 'mcphee-slideshow': {'id': 'McPhee-slideshow', 'deprecated': False},
+ 'metamail': {'id': 'metamail', 'deprecated': False},
+ 'minpack': {'id': 'Minpack', 'deprecated': False},
+ 'miros': {'id': 'MirOS', 'deprecated': False},
+ 'mit': {'id': 'MIT', 'deprecated': False},
+ 'mit-0': {'id': 'MIT-0', 'deprecated': False},
+ 'mit-advertising': {'id': 'MIT-advertising', 'deprecated': False},
+ 'mit-cmu': {'id': 'MIT-CMU', 'deprecated': False},
+ 'mit-enna': {'id': 'MIT-enna', 'deprecated': False},
+ 'mit-feh': {'id': 'MIT-feh', 'deprecated': False},
+ 'mit-festival': {'id': 'MIT-Festival', 'deprecated': False},
+ 'mit-khronos-old': {'id': 'MIT-Khronos-old', 'deprecated': False},
+ 'mit-modern-variant': {'id': 'MIT-Modern-Variant', 'deprecated': False},
+ 'mit-open-group': {'id': 'MIT-open-group', 'deprecated': False},
+ 'mit-testregex': {'id': 'MIT-testregex', 'deprecated': False},
+ 'mit-wu': {'id': 'MIT-Wu', 'deprecated': False},
+ 'mitnfa': {'id': 'MITNFA', 'deprecated': False},
+ 'mmixware': {'id': 'MMIXware', 'deprecated': False},
+ 'motosoto': {'id': 'Motosoto', 'deprecated': False},
+ 'mpeg-ssg': {'id': 'MPEG-SSG', 'deprecated': False},
+ 'mpi-permissive': {'id': 'mpi-permissive', 'deprecated': False},
+ 'mpich2': {'id': 'mpich2', 'deprecated': False},
+ 'mpl-1.0': {'id': 'MPL-1.0', 'deprecated': False},
+ 'mpl-1.1': {'id': 'MPL-1.1', 'deprecated': False},
+ 'mpl-2.0': {'id': 'MPL-2.0', 'deprecated': False},
+ 'mpl-2.0-no-copyleft-exception': {'id': 'MPL-2.0-no-copyleft-exception', 'deprecated': False},
+ 'mplus': {'id': 'mplus', 'deprecated': False},
+ 'ms-lpl': {'id': 'MS-LPL', 'deprecated': False},
+ 'ms-pl': {'id': 'MS-PL', 'deprecated': False},
+ 'ms-rl': {'id': 'MS-RL', 'deprecated': False},
+ 'mtll': {'id': 'MTLL', 'deprecated': False},
+ 'mulanpsl-1.0': {'id': 'MulanPSL-1.0', 'deprecated': False},
+ 'mulanpsl-2.0': {'id': 'MulanPSL-2.0', 'deprecated': False},
+ 'multics': {'id': 'Multics', 'deprecated': False},
+ 'mup': {'id': 'Mup', 'deprecated': False},
+ 'naist-2003': {'id': 'NAIST-2003', 'deprecated': False},
+ 'nasa-1.3': {'id': 'NASA-1.3', 'deprecated': False},
+ 'naumen': {'id': 'Naumen', 'deprecated': False},
+ 'nbpl-1.0': {'id': 'NBPL-1.0', 'deprecated': False},
+ 'ncbi-pd': {'id': 'NCBI-PD', 'deprecated': False},
+ 'ncgl-uk-2.0': {'id': 'NCGL-UK-2.0', 'deprecated': False},
+ 'ncl': {'id': 'NCL', 'deprecated': False},
+ 'ncsa': {'id': 'NCSA', 'deprecated': False},
+ 'net-snmp': {'id': 'Net-SNMP', 'deprecated': True},
+ 'netcdf': {'id': 'NetCDF', 'deprecated': False},
+ 'newsletr': {'id': 'Newsletr', 'deprecated': False},
+ 'ngpl': {'id': 'NGPL', 'deprecated': False},
+ 'nicta-1.0': {'id': 'NICTA-1.0', 'deprecated': False},
+ 'nist-pd': {'id': 'NIST-PD', 'deprecated': False},
+ 'nist-pd-fallback': {'id': 'NIST-PD-fallback', 'deprecated': False},
+ 'nist-software': {'id': 'NIST-Software', 'deprecated': False},
+ 'nlod-1.0': {'id': 'NLOD-1.0', 'deprecated': False},
+ 'nlod-2.0': {'id': 'NLOD-2.0', 'deprecated': False},
+ 'nlpl': {'id': 'NLPL', 'deprecated': False},
+ 'nokia': {'id': 'Nokia', 'deprecated': False},
+ 'nosl': {'id': 'NOSL', 'deprecated': False},
+ 'noweb': {'id': 'Noweb', 'deprecated': False},
+ 'npl-1.0': {'id': 'NPL-1.0', 'deprecated': False},
+ 'npl-1.1': {'id': 'NPL-1.1', 'deprecated': False},
+ 'nposl-3.0': {'id': 'NPOSL-3.0', 'deprecated': False},
+ 'nrl': {'id': 'NRL', 'deprecated': False},
+ 'ntp': {'id': 'NTP', 'deprecated': False},
+ 'ntp-0': {'id': 'NTP-0', 'deprecated': False},
+ 'nunit': {'id': 'Nunit', 'deprecated': True},
+ 'o-uda-1.0': {'id': 'O-UDA-1.0', 'deprecated': False},
+ 'oar': {'id': 'OAR', 'deprecated': False},
+ 'occt-pl': {'id': 'OCCT-PL', 'deprecated': False},
+ 'oclc-2.0': {'id': 'OCLC-2.0', 'deprecated': False},
+ 'odbl-1.0': {'id': 'ODbL-1.0', 'deprecated': False},
+ 'odc-by-1.0': {'id': 'ODC-By-1.0', 'deprecated': False},
+ 'offis': {'id': 'OFFIS', 'deprecated': False},
+ 'ofl-1.0': {'id': 'OFL-1.0', 'deprecated': False},
+ 'ofl-1.0-no-rfn': {'id': 'OFL-1.0-no-RFN', 'deprecated': False},
+ 'ofl-1.0-rfn': {'id': 'OFL-1.0-RFN', 'deprecated': False},
+ 'ofl-1.1': {'id': 'OFL-1.1', 'deprecated': False},
+ 'ofl-1.1-no-rfn': {'id': 'OFL-1.1-no-RFN', 'deprecated': False},
+ 'ofl-1.1-rfn': {'id': 'OFL-1.1-RFN', 'deprecated': False},
+ 'ogc-1.0': {'id': 'OGC-1.0', 'deprecated': False},
+ 'ogdl-taiwan-1.0': {'id': 'OGDL-Taiwan-1.0', 'deprecated': False},
+ 'ogl-canada-2.0': {'id': 'OGL-Canada-2.0', 'deprecated': False},
+ 'ogl-uk-1.0': {'id': 'OGL-UK-1.0', 'deprecated': False},
+ 'ogl-uk-2.0': {'id': 'OGL-UK-2.0', 'deprecated': False},
+ 'ogl-uk-3.0': {'id': 'OGL-UK-3.0', 'deprecated': False},
+ 'ogtsl': {'id': 'OGTSL', 'deprecated': False},
+ 'oldap-1.1': {'id': 'OLDAP-1.1', 'deprecated': False},
+ 'oldap-1.2': {'id': 'OLDAP-1.2', 'deprecated': False},
+ 'oldap-1.3': {'id': 'OLDAP-1.3', 'deprecated': False},
+ 'oldap-1.4': {'id': 'OLDAP-1.4', 'deprecated': False},
+ 'oldap-2.0': {'id': 'OLDAP-2.0', 'deprecated': False},
+ 'oldap-2.0.1': {'id': 'OLDAP-2.0.1', 'deprecated': False},
+ 'oldap-2.1': {'id': 'OLDAP-2.1', 'deprecated': False},
+ 'oldap-2.2': {'id': 'OLDAP-2.2', 'deprecated': False},
+ 'oldap-2.2.1': {'id': 'OLDAP-2.2.1', 'deprecated': False},
+ 'oldap-2.2.2': {'id': 'OLDAP-2.2.2', 'deprecated': False},
+ 'oldap-2.3': {'id': 'OLDAP-2.3', 'deprecated': False},
+ 'oldap-2.4': {'id': 'OLDAP-2.4', 'deprecated': False},
+ 'oldap-2.5': {'id': 'OLDAP-2.5', 'deprecated': False},
+ 'oldap-2.6': {'id': 'OLDAP-2.6', 'deprecated': False},
+ 'oldap-2.7': {'id': 'OLDAP-2.7', 'deprecated': False},
+ 'oldap-2.8': {'id': 'OLDAP-2.8', 'deprecated': False},
+ 'olfl-1.3': {'id': 'OLFL-1.3', 'deprecated': False},
+ 'oml': {'id': 'OML', 'deprecated': False},
+ 'openpbs-2.3': {'id': 'OpenPBS-2.3', 'deprecated': False},
+ 'openssl': {'id': 'OpenSSL', 'deprecated': False},
+ 'openssl-standalone': {'id': 'OpenSSL-standalone', 'deprecated': False},
+ 'openvision': {'id': 'OpenVision', 'deprecated': False},
+ 'opl-1.0': {'id': 'OPL-1.0', 'deprecated': False},
+ 'opl-uk-3.0': {'id': 'OPL-UK-3.0', 'deprecated': False},
+ 'opubl-1.0': {'id': 'OPUBL-1.0', 'deprecated': False},
+ 'oset-pl-2.1': {'id': 'OSET-PL-2.1', 'deprecated': False},
+ 'osl-1.0': {'id': 'OSL-1.0', 'deprecated': False},
+ 'osl-1.1': {'id': 'OSL-1.1', 'deprecated': False},
+ 'osl-2.0': {'id': 'OSL-2.0', 'deprecated': False},
+ 'osl-2.1': {'id': 'OSL-2.1', 'deprecated': False},
+ 'osl-3.0': {'id': 'OSL-3.0', 'deprecated': False},
+ 'padl': {'id': 'PADL', 'deprecated': False},
+ 'parity-6.0.0': {'id': 'Parity-6.0.0', 'deprecated': False},
+ 'parity-7.0.0': {'id': 'Parity-7.0.0', 'deprecated': False},
+ 'pddl-1.0': {'id': 'PDDL-1.0', 'deprecated': False},
+ 'php-3.0': {'id': 'PHP-3.0', 'deprecated': False},
+ 'php-3.01': {'id': 'PHP-3.01', 'deprecated': False},
+ 'pixar': {'id': 'Pixar', 'deprecated': False},
+ 'pkgconf': {'id': 'pkgconf', 'deprecated': False},
+ 'plexus': {'id': 'Plexus', 'deprecated': False},
+ 'pnmstitch': {'id': 'pnmstitch', 'deprecated': False},
+ 'polyform-noncommercial-1.0.0': {'id': 'PolyForm-Noncommercial-1.0.0', 'deprecated': False},
+ 'polyform-small-business-1.0.0': {'id': 'PolyForm-Small-Business-1.0.0', 'deprecated': False},
+ 'postgresql': {'id': 'PostgreSQL', 'deprecated': False},
+ 'ppl': {'id': 'PPL', 'deprecated': False},
+ 'psf-2.0': {'id': 'PSF-2.0', 'deprecated': False},
+ 'psfrag': {'id': 'psfrag', 'deprecated': False},
+ 'psutils': {'id': 'psutils', 'deprecated': False},
+ 'python-2.0': {'id': 'Python-2.0', 'deprecated': False},
+ 'python-2.0.1': {'id': 'Python-2.0.1', 'deprecated': False},
+ 'python-ldap': {'id': 'python-ldap', 'deprecated': False},
+ 'qhull': {'id': 'Qhull', 'deprecated': False},
+ 'qpl-1.0': {'id': 'QPL-1.0', 'deprecated': False},
+ 'qpl-1.0-inria-2004': {'id': 'QPL-1.0-INRIA-2004', 'deprecated': False},
+ 'radvd': {'id': 'radvd', 'deprecated': False},
+ 'rdisc': {'id': 'Rdisc', 'deprecated': False},
+ 'rhecos-1.1': {'id': 'RHeCos-1.1', 'deprecated': False},
+ 'rpl-1.1': {'id': 'RPL-1.1', 'deprecated': False},
+ 'rpl-1.5': {'id': 'RPL-1.5', 'deprecated': False},
+ 'rpsl-1.0': {'id': 'RPSL-1.0', 'deprecated': False},
+ 'rsa-md': {'id': 'RSA-MD', 'deprecated': False},
+ 'rscpl': {'id': 'RSCPL', 'deprecated': False},
+ 'ruby': {'id': 'Ruby', 'deprecated': False},
+ 'ruby-pty': {'id': 'Ruby-pty', 'deprecated': False},
+ 'sax-pd': {'id': 'SAX-PD', 'deprecated': False},
+ 'sax-pd-2.0': {'id': 'SAX-PD-2.0', 'deprecated': False},
+ 'saxpath': {'id': 'Saxpath', 'deprecated': False},
+ 'scea': {'id': 'SCEA', 'deprecated': False},
+ 'schemereport': {'id': 'SchemeReport', 'deprecated': False},
+ 'sendmail': {'id': 'Sendmail', 'deprecated': False},
+ 'sendmail-8.23': {'id': 'Sendmail-8.23', 'deprecated': False},
+ 'sgi-b-1.0': {'id': 'SGI-B-1.0', 'deprecated': False},
+ 'sgi-b-1.1': {'id': 'SGI-B-1.1', 'deprecated': False},
+ 'sgi-b-2.0': {'id': 'SGI-B-2.0', 'deprecated': False},
+ 'sgi-opengl': {'id': 'SGI-OpenGL', 'deprecated': False},
+ 'sgp4': {'id': 'SGP4', 'deprecated': False},
+ 'shl-0.5': {'id': 'SHL-0.5', 'deprecated': False},
+ 'shl-0.51': {'id': 'SHL-0.51', 'deprecated': False},
+ 'simpl-2.0': {'id': 'SimPL-2.0', 'deprecated': False},
+ 'sissl': {'id': 'SISSL', 'deprecated': False},
+ 'sissl-1.2': {'id': 'SISSL-1.2', 'deprecated': False},
+ 'sl': {'id': 'SL', 'deprecated': False},
+ 'sleepycat': {'id': 'Sleepycat', 'deprecated': False},
+ 'smlnj': {'id': 'SMLNJ', 'deprecated': False},
+ 'smppl': {'id': 'SMPPL', 'deprecated': False},
+ 'snia': {'id': 'SNIA', 'deprecated': False},
+ 'snprintf': {'id': 'snprintf', 'deprecated': False},
+ 'softsurfer': {'id': 'softSurfer', 'deprecated': False},
+ 'soundex': {'id': 'Soundex', 'deprecated': False},
+ 'spencer-86': {'id': 'Spencer-86', 'deprecated': False},
+ 'spencer-94': {'id': 'Spencer-94', 'deprecated': False},
+ 'spencer-99': {'id': 'Spencer-99', 'deprecated': False},
+ 'spl-1.0': {'id': 'SPL-1.0', 'deprecated': False},
+ 'ssh-keyscan': {'id': 'ssh-keyscan', 'deprecated': False},
+ 'ssh-openssh': {'id': 'SSH-OpenSSH', 'deprecated': False},
+ 'ssh-short': {'id': 'SSH-short', 'deprecated': False},
+ 'ssleay-standalone': {'id': 'SSLeay-standalone', 'deprecated': False},
+ 'sspl-1.0': {'id': 'SSPL-1.0', 'deprecated': False},
+ 'standardml-nj': {'id': 'StandardML-NJ', 'deprecated': True},
+ 'sugarcrm-1.1.3': {'id': 'SugarCRM-1.1.3', 'deprecated': False},
+ 'sun-ppp': {'id': 'Sun-PPP', 'deprecated': False},
+ 'sun-ppp-2000': {'id': 'Sun-PPP-2000', 'deprecated': False},
+ 'sunpro': {'id': 'SunPro', 'deprecated': False},
+ 'swl': {'id': 'SWL', 'deprecated': False},
+ 'swrule': {'id': 'swrule', 'deprecated': False},
+ 'symlinks': {'id': 'Symlinks', 'deprecated': False},
+ 'tapr-ohl-1.0': {'id': 'TAPR-OHL-1.0', 'deprecated': False},
+ 'tcl': {'id': 'TCL', 'deprecated': False},
+ 'tcp-wrappers': {'id': 'TCP-wrappers', 'deprecated': False},
+ 'termreadkey': {'id': 'TermReadKey', 'deprecated': False},
+ 'tgppl-1.0': {'id': 'TGPPL-1.0', 'deprecated': False},
+ 'threeparttable': {'id': 'threeparttable', 'deprecated': False},
+ 'tmate': {'id': 'TMate', 'deprecated': False},
+ 'torque-1.1': {'id': 'TORQUE-1.1', 'deprecated': False},
+ 'tosl': {'id': 'TOSL', 'deprecated': False},
+ 'tpdl': {'id': 'TPDL', 'deprecated': False},
+ 'tpl-1.0': {'id': 'TPL-1.0', 'deprecated': False},
+ 'ttwl': {'id': 'TTWL', 'deprecated': False},
+ 'ttyp0': {'id': 'TTYP0', 'deprecated': False},
+ 'tu-berlin-1.0': {'id': 'TU-Berlin-1.0', 'deprecated': False},
+ 'tu-berlin-2.0': {'id': 'TU-Berlin-2.0', 'deprecated': False},
+ 'ubuntu-font-1.0': {'id': 'Ubuntu-font-1.0', 'deprecated': False},
+ 'ucar': {'id': 'UCAR', 'deprecated': False},
+ 'ucl-1.0': {'id': 'UCL-1.0', 'deprecated': False},
+ 'ulem': {'id': 'ulem', 'deprecated': False},
+ 'umich-merit': {'id': 'UMich-Merit', 'deprecated': False},
+ 'unicode-3.0': {'id': 'Unicode-3.0', 'deprecated': False},
+ 'unicode-dfs-2015': {'id': 'Unicode-DFS-2015', 'deprecated': False},
+ 'unicode-dfs-2016': {'id': 'Unicode-DFS-2016', 'deprecated': False},
+ 'unicode-tou': {'id': 'Unicode-TOU', 'deprecated': False},
+ 'unixcrypt': {'id': 'UnixCrypt', 'deprecated': False},
+ 'unlicense': {'id': 'Unlicense', 'deprecated': False},
+ 'upl-1.0': {'id': 'UPL-1.0', 'deprecated': False},
+ 'urt-rle': {'id': 'URT-RLE', 'deprecated': False},
+ 'vim': {'id': 'Vim', 'deprecated': False},
+ 'vostrom': {'id': 'VOSTROM', 'deprecated': False},
+ 'vsl-1.0': {'id': 'VSL-1.0', 'deprecated': False},
+ 'w3c': {'id': 'W3C', 'deprecated': False},
+ 'w3c-19980720': {'id': 'W3C-19980720', 'deprecated': False},
+ 'w3c-20150513': {'id': 'W3C-20150513', 'deprecated': False},
+ 'w3m': {'id': 'w3m', 'deprecated': False},
+ 'watcom-1.0': {'id': 'Watcom-1.0', 'deprecated': False},
+ 'widget-workshop': {'id': 'Widget-Workshop', 'deprecated': False},
+ 'wsuipa': {'id': 'Wsuipa', 'deprecated': False},
+ 'wtfpl': {'id': 'WTFPL', 'deprecated': False},
+ 'wxwindows': {'id': 'wxWindows', 'deprecated': True},
+ 'x11': {'id': 'X11', 'deprecated': False},
+ 'x11-distribute-modifications-variant': {'id': 'X11-distribute-modifications-variant', 'deprecated': False},
+ 'x11-swapped': {'id': 'X11-swapped', 'deprecated': False},
+ 'xdebug-1.03': {'id': 'Xdebug-1.03', 'deprecated': False},
+ 'xerox': {'id': 'Xerox', 'deprecated': False},
+ 'xfig': {'id': 'Xfig', 'deprecated': False},
+ 'xfree86-1.1': {'id': 'XFree86-1.1', 'deprecated': False},
+ 'xinetd': {'id': 'xinetd', 'deprecated': False},
+ 'xkeyboard-config-zinoviev': {'id': 'xkeyboard-config-Zinoviev', 'deprecated': False},
+ 'xlock': {'id': 'xlock', 'deprecated': False},
+ 'xnet': {'id': 'Xnet', 'deprecated': False},
+ 'xpp': {'id': 'xpp', 'deprecated': False},
+ 'xskat': {'id': 'XSkat', 'deprecated': False},
+ 'xzoom': {'id': 'xzoom', 'deprecated': False},
+ 'ypl-1.0': {'id': 'YPL-1.0', 'deprecated': False},
+ 'ypl-1.1': {'id': 'YPL-1.1', 'deprecated': False},
+ 'zed': {'id': 'Zed', 'deprecated': False},
+ 'zeeff': {'id': 'Zeeff', 'deprecated': False},
+ 'zend-2.0': {'id': 'Zend-2.0', 'deprecated': False},
+ 'zimbra-1.3': {'id': 'Zimbra-1.3', 'deprecated': False},
+ 'zimbra-1.4': {'id': 'Zimbra-1.4', 'deprecated': False},
+ 'zlib': {'id': 'Zlib', 'deprecated': False},
+ 'zlib-acknowledgement': {'id': 'zlib-acknowledgement', 'deprecated': False},
+ 'zpl-1.1': {'id': 'ZPL-1.1', 'deprecated': False},
+ 'zpl-2.0': {'id': 'ZPL-2.0', 'deprecated': False},
+ 'zpl-2.1': {'id': 'ZPL-2.1', 'deprecated': False},
+}
+
+EXCEPTIONS: dict[str, SPDXException] = {
+ '389-exception': {'id': '389-exception', 'deprecated': False},
+ 'asterisk-exception': {'id': 'Asterisk-exception', 'deprecated': False},
+ 'asterisk-linking-protocols-exception': {'id': 'Asterisk-linking-protocols-exception', 'deprecated': False},
+ 'autoconf-exception-2.0': {'id': 'Autoconf-exception-2.0', 'deprecated': False},
+ 'autoconf-exception-3.0': {'id': 'Autoconf-exception-3.0', 'deprecated': False},
+ 'autoconf-exception-generic': {'id': 'Autoconf-exception-generic', 'deprecated': False},
+ 'autoconf-exception-generic-3.0': {'id': 'Autoconf-exception-generic-3.0', 'deprecated': False},
+ 'autoconf-exception-macro': {'id': 'Autoconf-exception-macro', 'deprecated': False},
+ 'bison-exception-1.24': {'id': 'Bison-exception-1.24', 'deprecated': False},
+ 'bison-exception-2.2': {'id': 'Bison-exception-2.2', 'deprecated': False},
+ 'bootloader-exception': {'id': 'Bootloader-exception', 'deprecated': False},
+ 'classpath-exception-2.0': {'id': 'Classpath-exception-2.0', 'deprecated': False},
+ 'clisp-exception-2.0': {'id': 'CLISP-exception-2.0', 'deprecated': False},
+ 'cryptsetup-openssl-exception': {'id': 'cryptsetup-OpenSSL-exception', 'deprecated': False},
+ 'digirule-foss-exception': {'id': 'DigiRule-FOSS-exception', 'deprecated': False},
+ 'ecos-exception-2.0': {'id': 'eCos-exception-2.0', 'deprecated': False},
+ 'erlang-otp-linking-exception': {'id': 'erlang-otp-linking-exception', 'deprecated': False},
+ 'fawkes-runtime-exception': {'id': 'Fawkes-Runtime-exception', 'deprecated': False},
+ 'fltk-exception': {'id': 'FLTK-exception', 'deprecated': False},
+ 'fmt-exception': {'id': 'fmt-exception', 'deprecated': False},
+ 'font-exception-2.0': {'id': 'Font-exception-2.0', 'deprecated': False},
+ 'freertos-exception-2.0': {'id': 'freertos-exception-2.0', 'deprecated': False},
+ 'gcc-exception-2.0': {'id': 'GCC-exception-2.0', 'deprecated': False},
+ 'gcc-exception-2.0-note': {'id': 'GCC-exception-2.0-note', 'deprecated': False},
+ 'gcc-exception-3.1': {'id': 'GCC-exception-3.1', 'deprecated': False},
+ 'gmsh-exception': {'id': 'Gmsh-exception', 'deprecated': False},
+ 'gnat-exception': {'id': 'GNAT-exception', 'deprecated': False},
+ 'gnome-examples-exception': {'id': 'GNOME-examples-exception', 'deprecated': False},
+ 'gnu-compiler-exception': {'id': 'GNU-compiler-exception', 'deprecated': False},
+ 'gnu-javamail-exception': {'id': 'gnu-javamail-exception', 'deprecated': False},
+ 'gpl-3.0-interface-exception': {'id': 'GPL-3.0-interface-exception', 'deprecated': False},
+ 'gpl-3.0-linking-exception': {'id': 'GPL-3.0-linking-exception', 'deprecated': False},
+ 'gpl-3.0-linking-source-exception': {'id': 'GPL-3.0-linking-source-exception', 'deprecated': False},
+ 'gpl-cc-1.0': {'id': 'GPL-CC-1.0', 'deprecated': False},
+ 'gstreamer-exception-2005': {'id': 'GStreamer-exception-2005', 'deprecated': False},
+ 'gstreamer-exception-2008': {'id': 'GStreamer-exception-2008', 'deprecated': False},
+ 'i2p-gpl-java-exception': {'id': 'i2p-gpl-java-exception', 'deprecated': False},
+ 'kicad-libraries-exception': {'id': 'KiCad-libraries-exception', 'deprecated': False},
+ 'lgpl-3.0-linking-exception': {'id': 'LGPL-3.0-linking-exception', 'deprecated': False},
+ 'libpri-openh323-exception': {'id': 'libpri-OpenH323-exception', 'deprecated': False},
+ 'libtool-exception': {'id': 'Libtool-exception', 'deprecated': False},
+ 'linux-syscall-note': {'id': 'Linux-syscall-note', 'deprecated': False},
+ 'llgpl': {'id': 'LLGPL', 'deprecated': False},
+ 'llvm-exception': {'id': 'LLVM-exception', 'deprecated': False},
+ 'lzma-exception': {'id': 'LZMA-exception', 'deprecated': False},
+ 'mif-exception': {'id': 'mif-exception', 'deprecated': False},
+ 'nokia-qt-exception-1.1': {'id': 'Nokia-Qt-exception-1.1', 'deprecated': True},
+ 'ocaml-lgpl-linking-exception': {'id': 'OCaml-LGPL-linking-exception', 'deprecated': False},
+ 'occt-exception-1.0': {'id': 'OCCT-exception-1.0', 'deprecated': False},
+ 'openjdk-assembly-exception-1.0': {'id': 'OpenJDK-assembly-exception-1.0', 'deprecated': False},
+ 'openvpn-openssl-exception': {'id': 'openvpn-openssl-exception', 'deprecated': False},
+ 'pcre2-exception': {'id': 'PCRE2-exception', 'deprecated': False},
+ 'ps-or-pdf-font-exception-20170817': {'id': 'PS-or-PDF-font-exception-20170817', 'deprecated': False},
+ 'qpl-1.0-inria-2004-exception': {'id': 'QPL-1.0-INRIA-2004-exception', 'deprecated': False},
+ 'qt-gpl-exception-1.0': {'id': 'Qt-GPL-exception-1.0', 'deprecated': False},
+ 'qt-lgpl-exception-1.1': {'id': 'Qt-LGPL-exception-1.1', 'deprecated': False},
+ 'qwt-exception-1.0': {'id': 'Qwt-exception-1.0', 'deprecated': False},
+ 'romic-exception': {'id': 'romic-exception', 'deprecated': False},
+ 'rrdtool-floss-exception-2.0': {'id': 'RRDtool-FLOSS-exception-2.0', 'deprecated': False},
+ 'sane-exception': {'id': 'SANE-exception', 'deprecated': False},
+ 'shl-2.0': {'id': 'SHL-2.0', 'deprecated': False},
+ 'shl-2.1': {'id': 'SHL-2.1', 'deprecated': False},
+ 'stunnel-exception': {'id': 'stunnel-exception', 'deprecated': False},
+ 'swi-exception': {'id': 'SWI-exception', 'deprecated': False},
+ 'swift-exception': {'id': 'Swift-exception', 'deprecated': False},
+ 'texinfo-exception': {'id': 'Texinfo-exception', 'deprecated': False},
+ 'u-boot-exception-2.0': {'id': 'u-boot-exception-2.0', 'deprecated': False},
+ 'ubdl-exception': {'id': 'UBDL-exception', 'deprecated': False},
+ 'universal-foss-exception-1.0': {'id': 'Universal-FOSS-exception-1.0', 'deprecated': False},
+ 'vsftpd-openssl-exception': {'id': 'vsftpd-openssl-exception', 'deprecated': False},
+ 'wxwindows-exception-3.1': {'id': 'WxWindows-exception-3.1', 'deprecated': False},
+ 'x11vnc-openssl-exception': {'id': 'x11vnc-openssl-exception', 'deprecated': False},
+}
diff --git a/lib/packaging/markers.py b/lib/packaging/markers.py
index 7ac7bb69..fb7f49cf 100644
--- a/lib/packaging/markers.py
+++ b/lib/packaging/markers.py
@@ -18,9 +18,9 @@ from .utils import canonicalize_name
__all__ = [
"InvalidMarker",
+ "Marker",
"UndefinedComparison",
"UndefinedEnvironmentName",
- "Marker",
"default_environment",
]
@@ -232,7 +232,7 @@ def _evaluate_markers(markers: MarkerList, environment: dict[str, str]) -> bool:
def format_full_version(info: sys._version_info) -> str:
- version = "{0.major}.{0.minor}.{0.micro}".format(info)
+ version = f"{info.major}.{info.minor}.{info.micro}"
kind = info.releaselevel
if kind != "final":
version += kind[0] + str(info.serial)
@@ -309,12 +309,6 @@ class Marker:
"""
current_environment = cast("dict[str, str]", default_environment())
current_environment["extra"] = ""
- # Work around platform.python_version() returning something that is not PEP 440
- # compliant for non-tagged Python builds. We preserve default_environment()'s
- # behavior of returning platform.python_version() verbatim, and leave it to the
- # caller to provide a syntactically valid version if they want to override it.
- if current_environment["python_full_version"].endswith("+"):
- current_environment["python_full_version"] += "local"
if environment is not None:
current_environment.update(environment)
# The API used to allow setting extra to None. We need to handle this
@@ -322,4 +316,16 @@ class Marker:
if current_environment["extra"] is None:
current_environment["extra"] = ""
- return _evaluate_markers(self._markers, current_environment)
+ return _evaluate_markers(
+ self._markers, _repair_python_full_version(current_environment)
+ )
+
+
+def _repair_python_full_version(env: dict[str, str]) -> dict[str, str]:
+ """
+ Work around platform.python_version() returning something that is not PEP 440
+ compliant for non-tagged Python builds.
+ """
+ if env["python_full_version"].endswith("+"):
+ env["python_full_version"] += "local"
+ return env
diff --git a/lib/packaging/metadata.py b/lib/packaging/metadata.py
index eb8dc844..721f411c 100644
--- a/lib/packaging/metadata.py
+++ b/lib/packaging/metadata.py
@@ -5,6 +5,8 @@ import email.header
import email.message
import email.parser
import email.policy
+import pathlib
+import sys
import typing
from typing import (
Any,
@@ -15,15 +17,16 @@ from typing import (
cast,
)
-from . import requirements, specifiers, utils
+from . import licenses, requirements, specifiers, utils
from . import version as version_module
+from .licenses import NormalizedLicenseExpression
T = typing.TypeVar("T")
-try:
- ExceptionGroup
-except NameError: # pragma: no cover
+if sys.version_info >= (3, 11): # pragma: no cover
+ ExceptionGroup = ExceptionGroup
+else: # pragma: no cover
class ExceptionGroup(Exception):
"""A minimal implementation of :external:exc:`ExceptionGroup` from Python 3.11.
@@ -42,9 +45,6 @@ except NameError: # pragma: no cover
def __repr__(self) -> str:
return f"{self.__class__.__name__}({self.message!r}, {self.exceptions!r})"
-else: # pragma: no cover
- ExceptionGroup = ExceptionGroup
-
class InvalidMetadata(ValueError):
"""A metadata field contains invalid data."""
@@ -128,6 +128,10 @@ class RawMetadata(TypedDict, total=False):
# No new fields were added in PEP 685, just some edge case were
# tightened up to provide better interoptability.
+ # Metadata 2.4 - PEP 639
+ license_expression: str
+ license_files: list[str]
+
_STRING_FIELDS = {
"author",
@@ -137,6 +141,7 @@ _STRING_FIELDS = {
"download_url",
"home_page",
"license",
+ "license_expression",
"maintainer",
"maintainer_email",
"metadata_version",
@@ -149,6 +154,7 @@ _STRING_FIELDS = {
_LIST_FIELDS = {
"classifiers",
"dynamic",
+ "license_files",
"obsoletes",
"obsoletes_dist",
"platforms",
@@ -167,7 +173,7 @@ _DICT_FIELDS = {
def _parse_keywords(data: str) -> list[str]:
- """Split a string of comma-separate keyboards into a list of keywords."""
+ """Split a string of comma-separated keywords into a list of keywords."""
return [k.strip() for k in data.split(",")]
@@ -216,16 +222,18 @@ def _get_payload(msg: email.message.Message, source: bytes | str) -> str:
# If our source is a str, then our caller has managed encodings for us,
# and we don't need to deal with it.
if isinstance(source, str):
- payload: str = msg.get_payload()
+ payload = msg.get_payload()
+ assert isinstance(payload, str)
return payload
# If our source is a bytes, then we're managing the encoding and we need
# to deal with it.
else:
- bpayload: bytes = msg.get_payload(decode=True)
+ bpayload = msg.get_payload(decode=True)
+ assert isinstance(bpayload, bytes)
try:
return bpayload.decode("utf8", "strict")
- except UnicodeDecodeError:
- raise ValueError("payload in an invalid encoding")
+ except UnicodeDecodeError as exc:
+ raise ValueError("payload in an invalid encoding") from exc
# The various parse_FORMAT functions here are intended to be as lenient as
@@ -251,6 +259,8 @@ _EMAIL_TO_RAW_MAPPING = {
"home-page": "home_page",
"keywords": "keywords",
"license": "license",
+ "license-expression": "license_expression",
+ "license-file": "license_files",
"maintainer": "maintainer",
"maintainer-email": "maintainer_email",
"metadata-version": "metadata_version",
@@ -426,7 +436,7 @@ def parse_email(data: bytes | str) -> tuple[RawMetadata, dict[str, list[str]]]:
payload = _get_payload(parsed, data)
except ValueError:
unparsed.setdefault("description", []).append(
- parsed.get_payload(decode=isinstance(data, bytes))
+ parsed.get_payload(decode=isinstance(data, bytes)) # type: ignore[call-overload]
)
else:
if payload:
@@ -453,8 +463,8 @@ _NOT_FOUND = object()
# Keep the two values in sync.
-_VALID_METADATA_VERSIONS = ["1.0", "1.1", "1.2", "2.1", "2.2", "2.3"]
-_MetadataVersion = Literal["1.0", "1.1", "1.2", "2.1", "2.2", "2.3"]
+_VALID_METADATA_VERSIONS = ["1.0", "1.1", "1.2", "2.1", "2.2", "2.3", "2.4"]
+_MetadataVersion = Literal["1.0", "1.1", "1.2", "2.1", "2.2", "2.3", "2.4"]
_REQUIRED_ATTRS = frozenset(["metadata_version", "name", "version"])
@@ -535,7 +545,7 @@ class _Validator(Generic[T]):
except utils.InvalidName as exc:
raise self._invalid_metadata(
f"{value!r} is invalid for {{field}}", cause=exc
- )
+ ) from exc
else:
return value
@@ -547,7 +557,7 @@ class _Validator(Generic[T]):
except version_module.InvalidVersion as exc:
raise self._invalid_metadata(
f"{value!r} is invalid for {{field}}", cause=exc
- )
+ ) from exc
def _process_summary(self, value: str) -> str:
"""Check the field contains no newlines."""
@@ -591,10 +601,12 @@ class _Validator(Generic[T]):
for dynamic_field in map(str.lower, value):
if dynamic_field in {"name", "version", "metadata-version"}:
raise self._invalid_metadata(
- f"{value!r} is not allowed as a dynamic field"
+ f"{dynamic_field!r} is not allowed as a dynamic field"
)
elif dynamic_field not in _EMAIL_TO_RAW_MAPPING:
- raise self._invalid_metadata(f"{value!r} is not a valid dynamic field")
+ raise self._invalid_metadata(
+ f"{dynamic_field!r} is not a valid dynamic field"
+ )
return list(map(str.lower, value))
def _process_provides_extra(
@@ -608,7 +620,7 @@ class _Validator(Generic[T]):
except utils.InvalidName as exc:
raise self._invalid_metadata(
f"{name!r} is invalid for {{field}}", cause=exc
- )
+ ) from exc
else:
return normalized_names
@@ -618,7 +630,7 @@ class _Validator(Generic[T]):
except specifiers.InvalidSpecifier as exc:
raise self._invalid_metadata(
f"{value!r} is invalid for {{field}}", cause=exc
- )
+ ) from exc
def _process_requires_dist(
self,
@@ -629,10 +641,49 @@ class _Validator(Generic[T]):
for req in value:
reqs.append(requirements.Requirement(req))
except requirements.InvalidRequirement as exc:
- raise self._invalid_metadata(f"{req!r} is invalid for {{field}}", cause=exc)
+ raise self._invalid_metadata(
+ f"{req!r} is invalid for {{field}}", cause=exc
+ ) from exc
else:
return reqs
+ def _process_license_expression(
+ self, value: str
+ ) -> NormalizedLicenseExpression | None:
+ try:
+ return licenses.canonicalize_license_expression(value)
+ except ValueError as exc:
+ raise self._invalid_metadata(
+ f"{value!r} is invalid for {{field}}", cause=exc
+ ) from exc
+
+ def _process_license_files(self, value: list[str]) -> list[str]:
+ paths = []
+ for path in value:
+ if ".." in path:
+ raise self._invalid_metadata(
+ f"{path!r} is invalid for {{field}}, "
+ "parent directory indicators are not allowed"
+ )
+ if "*" in path:
+ raise self._invalid_metadata(
+ f"{path!r} is invalid for {{field}}, paths must be resolved"
+ )
+ if (
+ pathlib.PurePosixPath(path).is_absolute()
+ or pathlib.PureWindowsPath(path).is_absolute()
+ ):
+ raise self._invalid_metadata(
+ f"{path!r} is invalid for {{field}}, paths must be relative"
+ )
+ if pathlib.PureWindowsPath(path).as_posix() != path:
+ raise self._invalid_metadata(
+ f"{path!r} is invalid for {{field}}, "
+ "paths must use '/' delimiter"
+ )
+ paths.append(path)
+ return paths
+
class Metadata:
"""Representation of distribution metadata.
@@ -688,8 +739,8 @@ class Metadata:
field = _RAW_TO_EMAIL_MAPPING[key]
exc = InvalidMetadata(
field,
- "{field} introduced in metadata version "
- "{field_metadata_version}, not {metadata_version}",
+ f"{field} introduced in metadata version "
+ f"{field_metadata_version}, not {metadata_version}",
)
exceptions.append(exc)
continue
@@ -733,6 +784,8 @@ class Metadata:
metadata_version: _Validator[_MetadataVersion] = _Validator()
""":external:ref:`core-metadata-metadata-version`
(required; validated to be a valid metadata version)"""
+ # `name` is not normalized/typed to NormalizedName so as to provide access to
+ # the original/raw name.
name: _Validator[str] = _Validator()
""":external:ref:`core-metadata-name`
(required; validated using :func:`~packaging.utils.canonicalize_name` and its
@@ -770,6 +823,12 @@ class Metadata:
""":external:ref:`core-metadata-maintainer-email`"""
license: _Validator[str | None] = _Validator()
""":external:ref:`core-metadata-license`"""
+ license_expression: _Validator[NormalizedLicenseExpression | None] = _Validator(
+ added="2.4"
+ )
+ """:external:ref:`core-metadata-license-expression`"""
+ license_files: _Validator[list[str] | None] = _Validator(added="2.4")
+ """:external:ref:`core-metadata-license-file`"""
classifiers: _Validator[list[str] | None] = _Validator(added="1.1")
""":external:ref:`core-metadata-classifier`"""
requires_dist: _Validator[list[requirements.Requirement] | None] = _Validator(
diff --git a/lib/packaging/specifiers.py b/lib/packaging/specifiers.py
index 2fa75f7a..b30926af 100644
--- a/lib/packaging/specifiers.py
+++ b/lib/packaging/specifiers.py
@@ -234,7 +234,7 @@ class Specifier(BaseSpecifier):
"""
match = self._regex.search(spec)
if not match:
- raise InvalidSpecifier(f"Invalid specifier: '{spec}'")
+ raise InvalidSpecifier(f"Invalid specifier: {spec!r}")
self._spec: tuple[str, str] = (
match.group("operator").strip(),
@@ -256,7 +256,7 @@ class Specifier(BaseSpecifier):
# operators, and if they are if they are including an explicit
# prerelease.
operator, version = self._spec
- if operator in ["==", ">=", "<=", "~=", "==="]:
+ if operator in ["==", ">=", "<=", "~=", "===", ">", "<"]:
# The == specifier can include a trailing .*, if it does we
# want to remove before parsing.
if operator == "==" and version.endswith(".*"):
@@ -694,12 +694,18 @@ class SpecifierSet(BaseSpecifier):
specifiers (``>=3.0,!=3.1``), or no specifier at all.
"""
- def __init__(self, specifiers: str = "", prereleases: bool | None = None) -> None:
+ def __init__(
+ self,
+ specifiers: str | Iterable[Specifier] = "",
+ prereleases: bool | None = None,
+ ) -> None:
"""Initialize a SpecifierSet instance.
:param specifiers:
The string representation of a specifier or a comma-separated list of
specifiers which will be parsed and normalized before use.
+ May also be an iterable of ``Specifier`` instances, which will be used
+ as is.
:param prereleases:
This tells the SpecifierSet if it should accept prerelease versions if
applicable or not. The default of ``None`` will autodetect it from the
@@ -710,12 +716,17 @@ class SpecifierSet(BaseSpecifier):
raised.
"""
- # Split on `,` to break each individual specifier into it's own item, and
- # strip each item to remove leading/trailing whitespace.
- split_specifiers = [s.strip() for s in specifiers.split(",") if s.strip()]
+ if isinstance(specifiers, str):
+ # Split on `,` to break each individual specifier into its own item, and
+ # strip each item to remove leading/trailing whitespace.
+ split_specifiers = [s.strip() for s in specifiers.split(",") if s.strip()]
- # Make each individual specifier a Specifier and save in a frozen set for later.
- self._specs = frozenset(map(Specifier, split_specifiers))
+ # Make each individual specifier a Specifier and save in a frozen set
+ # for later.
+ self._specs = frozenset(map(Specifier, split_specifiers))
+ else:
+ # Save the supplied specifiers in a frozen set.
+ self._specs = frozenset(specifiers)
# Store our prereleases value so we can use it later to determine if
# we accept prereleases or not.
diff --git a/lib/packaging/tags.py b/lib/packaging/tags.py
index 6667d299..f5903402 100644
--- a/lib/packaging/tags.py
+++ b/lib/packaging/tags.py
@@ -25,7 +25,7 @@ from . import _manylinux, _musllinux
logger = logging.getLogger(__name__)
PythonVersion = Sequence[int]
-MacVersion = Tuple[int, int]
+AppleVersion = Tuple[int, int]
INTERPRETER_SHORT_NAMES: dict[str, str] = {
"python": "py", # Generic.
@@ -47,7 +47,7 @@ class Tag:
is also supported.
"""
- __slots__ = ["_interpreter", "_abi", "_platform", "_hash"]
+ __slots__ = ["_abi", "_hash", "_interpreter", "_platform"]
def __init__(self, interpreter: str, abi: str, platform: str) -> None:
self._interpreter = interpreter.lower()
@@ -235,9 +235,8 @@ def cpython_tags(
if use_abi3:
for minor_version in range(python_version[1] - 1, 1, -1):
for platform_ in platforms:
- interpreter = "cp{version}".format(
- version=_version_nodot((python_version[0], minor_version))
- )
+ version = _version_nodot((python_version[0], minor_version))
+ interpreter = f"cp{version}"
yield Tag(interpreter, "abi3", platform_)
@@ -363,7 +362,7 @@ def _mac_arch(arch: str, is_32bit: bool = _32_BIT_INTERPRETER) -> str:
return "i386"
-def _mac_binary_formats(version: MacVersion, cpu_arch: str) -> list[str]:
+def _mac_binary_formats(version: AppleVersion, cpu_arch: str) -> list[str]:
formats = [cpu_arch]
if cpu_arch == "x86_64":
if version < (10, 4):
@@ -396,7 +395,7 @@ def _mac_binary_formats(version: MacVersion, cpu_arch: str) -> list[str]:
def mac_platforms(
- version: MacVersion | None = None, arch: str | None = None
+ version: AppleVersion | None = None, arch: str | None = None
) -> Iterator[str]:
"""
Yields the platform tags for a macOS system.
@@ -408,7 +407,7 @@ def mac_platforms(
"""
version_str, _, cpu_arch = platform.mac_ver()
if version is None:
- version = cast("MacVersion", tuple(map(int, version_str.split(".")[:2])))
+ version = cast("AppleVersion", tuple(map(int, version_str.split(".")[:2])))
if version == (10, 16):
# When built against an older macOS SDK, Python will report macOS 10.16
# instead of the real version.
@@ -424,7 +423,7 @@ def mac_platforms(
stdout=subprocess.PIPE,
text=True,
).stdout
- version = cast("MacVersion", tuple(map(int, version_str.split(".")[:2])))
+ version = cast("AppleVersion", tuple(map(int, version_str.split(".")[:2])))
else:
version = version
if arch is None:
@@ -435,24 +434,22 @@ def mac_platforms(
if (10, 0) <= version and version < (11, 0):
# Prior to Mac OS 11, each yearly release of Mac OS bumped the
# "minor" version number. The major version was always 10.
+ major_version = 10
for minor_version in range(version[1], -1, -1):
- compat_version = 10, minor_version
+ compat_version = major_version, minor_version
binary_formats = _mac_binary_formats(compat_version, arch)
for binary_format in binary_formats:
- yield "macosx_{major}_{minor}_{binary_format}".format(
- major=10, minor=minor_version, binary_format=binary_format
- )
+ yield f"macosx_{major_version}_{minor_version}_{binary_format}"
if version >= (11, 0):
# Starting with Mac OS 11, each yearly release bumps the major version
# number. The minor versions are now the midyear updates.
+ minor_version = 0
for major_version in range(version[0], 10, -1):
- compat_version = major_version, 0
+ compat_version = major_version, minor_version
binary_formats = _mac_binary_formats(compat_version, arch)
for binary_format in binary_formats:
- yield "macosx_{major}_{minor}_{binary_format}".format(
- major=major_version, minor=0, binary_format=binary_format
- )
+ yield f"macosx_{major_version}_{minor_version}_{binary_format}"
if version >= (11, 0):
# Mac OS 11 on x86_64 is compatible with binaries from previous releases.
@@ -462,25 +459,75 @@ def mac_platforms(
# However, the "universal2" binary format can have a
# macOS version earlier than 11.0 when the x86_64 part of the binary supports
# that version of macOS.
+ major_version = 10
if arch == "x86_64":
for minor_version in range(16, 3, -1):
- compat_version = 10, minor_version
+ compat_version = major_version, minor_version
binary_formats = _mac_binary_formats(compat_version, arch)
for binary_format in binary_formats:
- yield "macosx_{major}_{minor}_{binary_format}".format(
- major=compat_version[0],
- minor=compat_version[1],
- binary_format=binary_format,
- )
+ yield f"macosx_{major_version}_{minor_version}_{binary_format}"
else:
for minor_version in range(16, 3, -1):
- compat_version = 10, minor_version
+ compat_version = major_version, minor_version
binary_format = "universal2"
- yield "macosx_{major}_{minor}_{binary_format}".format(
- major=compat_version[0],
- minor=compat_version[1],
- binary_format=binary_format,
- )
+ yield f"macosx_{major_version}_{minor_version}_{binary_format}"
+
+
+def ios_platforms(
+ version: AppleVersion | None = None, multiarch: str | None = None
+) -> Iterator[str]:
+ """
+ Yields the platform tags for an iOS system.
+
+ :param version: A two-item tuple specifying the iOS version to generate
+ platform tags for. Defaults to the current iOS version.
+ :param multiarch: The CPU architecture+ABI to generate platform tags for -
+ (the value used by `sys.implementation._multiarch` e.g.,
+ `arm64_iphoneos` or `x84_64_iphonesimulator`). Defaults to the current
+ multiarch value.
+ """
+ if version is None:
+ # if iOS is the current platform, ios_ver *must* be defined. However,
+ # it won't exist for CPython versions before 3.13, which causes a mypy
+ # error.
+ _, release, _, _ = platform.ios_ver() # type: ignore[attr-defined, unused-ignore]
+ version = cast("AppleVersion", tuple(map(int, release.split(".")[:2])))
+
+ if multiarch is None:
+ multiarch = sys.implementation._multiarch
+ multiarch = multiarch.replace("-", "_")
+
+ ios_platform_template = "ios_{major}_{minor}_{multiarch}"
+
+ # Consider any iOS major.minor version from the version requested, down to
+ # 12.0. 12.0 is the first iOS version that is known to have enough features
+ # to support CPython. Consider every possible minor release up to X.9. There
+ # highest the minor has ever gone is 8 (14.8 and 15.8) but having some extra
+ # candidates that won't ever match doesn't really hurt, and it saves us from
+ # having to keep an explicit list of known iOS versions in the code. Return
+ # the results descending order of version number.
+
+ # If the requested major version is less than 12, there won't be any matches.
+ if version[0] < 12:
+ return
+
+ # Consider the actual X.Y version that was requested.
+ yield ios_platform_template.format(
+ major=version[0], minor=version[1], multiarch=multiarch
+ )
+
+ # Consider every minor version from X.0 to the minor version prior to the
+ # version requested by the platform.
+ for minor in range(version[1] - 1, -1, -1):
+ yield ios_platform_template.format(
+ major=version[0], minor=minor, multiarch=multiarch
+ )
+
+ for major in range(version[0] - 1, 11, -1):
+ for minor in range(9, -1, -1):
+ yield ios_platform_template.format(
+ major=major, minor=minor, multiarch=multiarch
+ )
def _linux_platforms(is_32bit: bool = _32_BIT_INTERPRETER) -> Iterator[str]:
@@ -512,6 +559,8 @@ def platform_tags() -> Iterator[str]:
"""
if platform.system() == "Darwin":
return mac_platforms()
+ elif platform.system() == "iOS":
+ return ios_platforms()
elif platform.system() == "Linux":
return _linux_platforms()
else:
diff --git a/lib/packaging/utils.py b/lib/packaging/utils.py
index d33da5bb..23450953 100644
--- a/lib/packaging/utils.py
+++ b/lib/packaging/utils.py
@@ -4,11 +4,12 @@
from __future__ import annotations
+import functools
import re
from typing import NewType, Tuple, Union, cast
from .tags import Tag, parse_tag
-from .version import InvalidVersion, Version
+from .version import InvalidVersion, Version, _TrimmedRelease
BuildTag = Union[Tuple[()], Tuple[int, str]]
NormalizedName = NewType("NormalizedName", str)
@@ -54,52 +55,40 @@ def is_normalized_name(name: str) -> bool:
return _normalized_regex.match(name) is not None
+@functools.singledispatch
def canonicalize_version(
version: Version | str, *, strip_trailing_zero: bool = True
) -> str:
"""
- This is very similar to Version.__str__, but has one subtle difference
- with the way it handles the release segment.
+ Return a canonical form of a version as a string.
+
+ >>> canonicalize_version('1.0.1')
+ '1.0.1'
+
+ Per PEP 625, versions may have multiple canonical forms, differing
+ only by trailing zeros.
+
+ >>> canonicalize_version('1.0.0')
+ '1'
+ >>> canonicalize_version('1.0.0', strip_trailing_zero=False)
+ '1.0.0'
+
+ Invalid versions are returned unaltered.
+
+ >>> canonicalize_version('foo bar baz')
+ 'foo bar baz'
"""
- if isinstance(version, str):
- try:
- parsed = Version(version)
- except InvalidVersion:
- # Legacy versions cannot be normalized
- return version
- else:
- parsed = version
+ return str(_TrimmedRelease(str(version)) if strip_trailing_zero else version)
- parts = []
- # Epoch
- if parsed.epoch != 0:
- parts.append(f"{parsed.epoch}!")
-
- # Release segment
- release_segment = ".".join(str(x) for x in parsed.release)
- if strip_trailing_zero:
- # NB: This strips trailing '.0's to normalize
- release_segment = re.sub(r"(\.0)+$", "", release_segment)
- parts.append(release_segment)
-
- # Pre-release
- if parsed.pre is not None:
- parts.append("".join(str(x) for x in parsed.pre))
-
- # Post-release
- if parsed.post is not None:
- parts.append(f".post{parsed.post}")
-
- # Development release
- if parsed.dev is not None:
- parts.append(f".dev{parsed.dev}")
-
- # Local version segment
- if parsed.local is not None:
- parts.append(f"+{parsed.local}")
-
- return "".join(parts)
+@canonicalize_version.register
+def _(version: str, *, strip_trailing_zero: bool = True) -> str:
+ try:
+ parsed = Version(version)
+ except InvalidVersion:
+ # Legacy versions cannot be normalized
+ return version
+ return canonicalize_version(parsed, strip_trailing_zero=strip_trailing_zero)
def parse_wheel_filename(
@@ -107,28 +96,28 @@ def parse_wheel_filename(
) -> tuple[NormalizedName, Version, BuildTag, frozenset[Tag]]:
if not filename.endswith(".whl"):
raise InvalidWheelFilename(
- f"Invalid wheel filename (extension must be '.whl'): {filename}"
+ f"Invalid wheel filename (extension must be '.whl'): {filename!r}"
)
filename = filename[:-4]
dashes = filename.count("-")
if dashes not in (4, 5):
raise InvalidWheelFilename(
- f"Invalid wheel filename (wrong number of parts): {filename}"
+ f"Invalid wheel filename (wrong number of parts): {filename!r}"
)
parts = filename.split("-", dashes - 2)
name_part = parts[0]
# See PEP 427 for the rules on escaping the project name.
if "__" in name_part or re.match(r"^[\w\d._]*$", name_part, re.UNICODE) is None:
- raise InvalidWheelFilename(f"Invalid project name: {filename}")
+ raise InvalidWheelFilename(f"Invalid project name: {filename!r}")
name = canonicalize_name(name_part)
try:
version = Version(parts[1])
except InvalidVersion as e:
raise InvalidWheelFilename(
- f"Invalid wheel filename (invalid version): {filename}"
+ f"Invalid wheel filename (invalid version): {filename!r}"
) from e
if dashes == 5:
@@ -136,7 +125,7 @@ def parse_wheel_filename(
build_match = _build_tag_regex.match(build_part)
if build_match is None:
raise InvalidWheelFilename(
- f"Invalid build number: {build_part} in '{filename}'"
+ f"Invalid build number: {build_part} in {filename!r}"
)
build = cast(BuildTag, (int(build_match.group(1)), build_match.group(2)))
else:
@@ -153,14 +142,14 @@ def parse_sdist_filename(filename: str) -> tuple[NormalizedName, Version]:
else:
raise InvalidSdistFilename(
f"Invalid sdist filename (extension must be '.tar.gz' or '.zip'):"
- f" {filename}"
+ f" {filename!r}"
)
# We are requiring a PEP 440 version, which cannot contain dashes,
# so we split on the last dash.
name_part, sep, version_part = file_stem.rpartition("-")
if not sep:
- raise InvalidSdistFilename(f"Invalid sdist filename: {filename}")
+ raise InvalidSdistFilename(f"Invalid sdist filename: {filename!r}")
name = canonicalize_name(name_part)
@@ -168,7 +157,7 @@ def parse_sdist_filename(filename: str) -> tuple[NormalizedName, Version]:
version = Version(version_part)
except InvalidVersion as e:
raise InvalidSdistFilename(
- f"Invalid sdist filename (invalid version): {filename}"
+ f"Invalid sdist filename (invalid version): {filename!r}"
) from e
return (name, version)
diff --git a/lib/packaging/version.py b/lib/packaging/version.py
index 46bc2613..c9bbda20 100644
--- a/lib/packaging/version.py
+++ b/lib/packaging/version.py
@@ -15,7 +15,7 @@ from typing import Any, Callable, NamedTuple, SupportsInt, Tuple, Union
from ._structures import Infinity, InfinityType, NegativeInfinity, NegativeInfinityType
-__all__ = ["VERSION_PATTERN", "parse", "Version", "InvalidVersion"]
+__all__ = ["VERSION_PATTERN", "InvalidVersion", "Version", "parse"]
LocalType = Tuple[Union[int, str], ...]
@@ -199,7 +199,7 @@ class Version(_BaseVersion):
# Validate the version and parse it into pieces
match = self._regex.search(version)
if not match:
- raise InvalidVersion(f"Invalid version: '{version}'")
+ raise InvalidVersion(f"Invalid version: {version!r}")
# Store the parsed out pieces of the version
self._version = _Version(
@@ -232,7 +232,7 @@ class Version(_BaseVersion):
return f""
def __str__(self) -> str:
- """A string representation of the version that can be rounded-tripped.
+ """A string representation of the version that can be round-tripped.
>>> str(Version("1.0a5"))
'1.0a5'
@@ -350,8 +350,8 @@ class Version(_BaseVersion):
'1.2.3'
>>> Version("1.2.3+abc").public
'1.2.3'
- >>> Version("1.2.3+abc.dev1").public
- '1.2.3'
+ >>> Version("1!1.2.3dev1+abc").public
+ '1!1.2.3.dev1'
"""
return str(self).split("+", 1)[0]
@@ -363,7 +363,7 @@ class Version(_BaseVersion):
'1.2.3'
>>> Version("1.2.3+abc").base_version
'1.2.3'
- >>> Version("1!1.2.3+abc.dev1").base_version
+ >>> Version("1!1.2.3dev1+abc").base_version
'1!1.2.3'
The "base version" is the public version of the project without any pre or post
@@ -451,6 +451,23 @@ class Version(_BaseVersion):
return self.release[2] if len(self.release) >= 3 else 0
+class _TrimmedRelease(Version):
+ @property
+ def release(self) -> tuple[int, ...]:
+ """
+ Release segment without any trailing zeros.
+
+ >>> _TrimmedRelease('1.0.0').release
+ (1,)
+ >>> _TrimmedRelease('0.0').release
+ (0,)
+ """
+ rel = super().release
+ nonzeros = (index for index, val in enumerate(rel) if val)
+ last_nonzero = max(nonzeros, default=0)
+ return rel[: last_nonzero + 1]
+
+
def _parse_letter_version(
letter: str | None, number: str | bytes | SupportsInt | None
) -> tuple[str, int] | None:
@@ -476,7 +493,9 @@ def _parse_letter_version(
letter = "post"
return letter, int(number)
- if not letter and number:
+
+ assert not letter
+ if number:
# We assume if we are given a number, but we are not given a letter
# then this is using the implicit post release syntax (e.g. 1.0-1)
letter = "post"
diff --git a/lib/platformdirs/__init__.py b/lib/platformdirs/__init__.py
index 3f7d9490..afe8351d 100644
--- a/lib/platformdirs/__init__.py
+++ b/lib/platformdirs/__init__.py
@@ -19,18 +19,18 @@ if TYPE_CHECKING:
from pathlib import Path
from typing import Literal
+if sys.platform == "win32":
+ from platformdirs.windows import Windows as _Result
+elif sys.platform == "darwin":
+ from platformdirs.macos import MacOS as _Result
+else:
+ from platformdirs.unix import Unix as _Result
+
def _set_platform_dir_class() -> type[PlatformDirsABC]:
- if sys.platform == "win32":
- from platformdirs.windows import Windows as Result # noqa: PLC0415
- elif sys.platform == "darwin":
- from platformdirs.macos import MacOS as Result # noqa: PLC0415
- else:
- from platformdirs.unix import Unix as Result # noqa: PLC0415
-
if os.getenv("ANDROID_DATA") == "/data" and os.getenv("ANDROID_ROOT") == "/system":
if os.getenv("SHELL") or os.getenv("PREFIX"):
- return Result
+ return _Result
from platformdirs.android import _android_folder # noqa: PLC0415
@@ -39,10 +39,14 @@ def _set_platform_dir_class() -> type[PlatformDirsABC]:
return Android # return to avoid redefinition of a result
- return Result
+ return _Result
-PlatformDirs = _set_platform_dir_class() #: Currently active platform
+if TYPE_CHECKING:
+ # Work around mypy issue: https://github.com/python/mypy/issues/10962
+ PlatformDirs = _Result
+else:
+ PlatformDirs = _set_platform_dir_class() #: Currently active platform
AppDirs = PlatformDirs #: Backwards compatibility with appdirs
diff --git a/lib/platformdirs/android.py b/lib/platformdirs/android.py
index afd3141c..7004a852 100644
--- a/lib/platformdirs/android.py
+++ b/lib/platformdirs/android.py
@@ -117,7 +117,7 @@ class Android(PlatformDirsABC):
@lru_cache(maxsize=1)
-def _android_folder() -> str | None: # noqa: C901, PLR0912
+def _android_folder() -> str | None: # noqa: C901
""":return: base folder for the Android OS or None if it cannot be found"""
result: str | None = None
# type checker isn't happy with our "import android", just don't do this when type checking see
diff --git a/lib/platformdirs/api.py b/lib/platformdirs/api.py
index c50caa64..18d660e4 100644
--- a/lib/platformdirs/api.py
+++ b/lib/platformdirs/api.py
@@ -91,6 +91,12 @@ class PlatformDirsABC(ABC): # noqa: PLR0904
if self.ensure_exists:
Path(path).mkdir(parents=True, exist_ok=True)
+ def _first_item_as_path_if_multipath(self, directory: str) -> Path:
+ if self.multipath:
+ # If multipath is True, the first path is returned.
+ directory = directory.split(os.pathsep)[0]
+ return Path(directory)
+
@property
@abstractmethod
def user_data_dir(self) -> str:
diff --git a/lib/platformdirs/macos.py b/lib/platformdirs/macos.py
index eb1ba5df..e4b0391a 100644
--- a/lib/platformdirs/macos.py
+++ b/lib/platformdirs/macos.py
@@ -4,9 +4,13 @@ from __future__ import annotations
import os.path
import sys
+from typing import TYPE_CHECKING
from .api import PlatformDirsABC
+if TYPE_CHECKING:
+ from pathlib import Path
+
class MacOS(PlatformDirsABC):
"""
@@ -42,6 +46,11 @@ class MacOS(PlatformDirsABC):
return os.pathsep.join(path_list)
return path_list[0]
+ @property
+ def site_data_path(self) -> Path:
+ """:return: data path shared by users. Only return the first item, even if ``multipath`` is set to ``True``"""
+ return self._first_item_as_path_if_multipath(self.site_data_dir)
+
@property
def user_config_dir(self) -> str:
""":return: config directory tied to the user, same as `user_data_dir`"""
@@ -74,6 +83,11 @@ class MacOS(PlatformDirsABC):
return os.pathsep.join(path_list)
return path_list[0]
+ @property
+ def site_cache_path(self) -> Path:
+ """:return: cache path shared by users. Only return the first item, even if ``multipath`` is set to ``True``"""
+ return self._first_item_as_path_if_multipath(self.site_cache_dir)
+
@property
def user_state_dir(self) -> str:
""":return: state directory tied to the user, same as `user_data_dir`"""
diff --git a/lib/platformdirs/unix.py b/lib/platformdirs/unix.py
index 9500ade6..f1942e92 100644
--- a/lib/platformdirs/unix.py
+++ b/lib/platformdirs/unix.py
@@ -218,12 +218,6 @@ class Unix(PlatformDirsABC): # noqa: PLR0904
""":return: cache path shared by users. Only return the first item, even if ``multipath`` is set to ``True``"""
return self._first_item_as_path_if_multipath(self.site_cache_dir)
- def _first_item_as_path_if_multipath(self, directory: str) -> Path:
- if self.multipath:
- # If multipath is True, the first path is returned.
- directory = directory.split(os.pathsep)[0]
- return Path(directory)
-
def iter_config_dirs(self) -> Iterator[str]:
""":yield: all user and site configuration directories."""
yield self.user_config_dir
diff --git a/lib/platformdirs/version.py b/lib/platformdirs/version.py
index 6483ddce..afb49243 100644
--- a/lib/platformdirs/version.py
+++ b/lib/platformdirs/version.py
@@ -12,5 +12,5 @@ __version__: str
__version_tuple__: VERSION_TUPLE
version_tuple: VERSION_TUPLE
-__version__ = version = '4.2.2'
-__version_tuple__ = version_tuple = (4, 2, 2)
+__version__ = version = '4.3.6'
+__version_tuple__ = version_tuple = (4, 3, 6)
diff --git a/lib/plexapi/audio.py b/lib/plexapi/audio.py
index 686073a3..05d38a9c 100644
--- a/lib/plexapi/audio.py
+++ b/lib/plexapi/audio.py
@@ -33,6 +33,7 @@ class Audio(PlexPartialObject, PlayedUnplayedMixin):
distance (float): Sonic Distance of the item from the seed item.
fields (List<:class:`~plexapi.media.Field`>): List of field objects.
guid (str): Plex GUID for the artist, album, or track (plex://artist/5d07bcb0403c64029053ac4c).
+ images (List<:class:`~plexapi.media.Image`>): List of image objects.
index (int): Plex index number (often the track number).
key (str): API URL (/library/metadata/).
lastRatedAt (datetime): Datetime the item was last rated.
@@ -65,6 +66,7 @@ class Audio(PlexPartialObject, PlayedUnplayedMixin):
self.distance = utils.cast(float, data.attrib.get('distance'))
self.fields = self.findItems(data, media.Field)
self.guid = data.attrib.get('guid')
+ self.images = self.findItems(data, media.Image)
self.index = utils.cast(int, data.attrib.get('index'))
self.key = data.attrib.get('key', '')
self.lastRatedAt = utils.toDatetime(data.attrib.get('lastRatedAt'))
diff --git a/lib/plexapi/base.py b/lib/plexapi/base.py
index a7fa82ee..675ac5d9 100644
--- a/lib/plexapi/base.py
+++ b/lib/plexapi/base.py
@@ -17,7 +17,7 @@ PlexObjectT = TypeVar("PlexObjectT", bound='PlexObject')
MediaContainerT = TypeVar("MediaContainerT", bound="MediaContainer")
USER_DONT_RELOAD_FOR_KEYS = set()
-_DONT_RELOAD_FOR_KEYS = {'key'}
+_DONT_RELOAD_FOR_KEYS = {'key', 'sourceURI'}
OPERATORS = {
'exact': lambda v, q: v == q,
'iexact': lambda v, q: v.lower() == q.lower(),
@@ -71,7 +71,7 @@ class PlexObject:
self._details_key = self._buildDetailsKey()
def __repr__(self):
- uid = self._clean(self.firstAttr('_baseurl', 'ratingKey', 'id', 'key', 'playQueueID', 'uri'))
+ uid = self._clean(self.firstAttr('_baseurl', 'ratingKey', 'id', 'key', 'playQueueID', 'uri', 'type'))
name = self._clean(self.firstAttr('title', 'name', 'username', 'product', 'tag', 'value'))
return f"<{':'.join([p for p in [self.__class__.__name__, uid, name] if p])}>"
diff --git a/lib/plexapi/collection.py b/lib/plexapi/collection.py
index 1c3ba3f7..63ea8373 100644
--- a/lib/plexapi/collection.py
+++ b/lib/plexapi/collection.py
@@ -39,6 +39,7 @@ class Collection(
contentRating (str) Content rating (PG-13; NR; TV-G).
fields (List<:class:`~plexapi.media.Field`>): List of field objects.
guid (str): Plex GUID for the collection (collection://XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXX).
+ images (List<:class:`~plexapi.media.Image`>): List of image objects.
index (int): Plex index number for the collection.
key (str): API URL (/library/metadata/).
labels (List<:class:`~plexapi.media.Label`>): List of label objects.
@@ -82,6 +83,7 @@ class Collection(
self.contentRating = data.attrib.get('contentRating')
self.fields = self.findItems(data, media.Field)
self.guid = data.attrib.get('guid')
+ self.images = self.findItems(data, media.Image)
self.index = utils.cast(int, data.attrib.get('index'))
self.key = data.attrib.get('key', '').replace('/children', '') # FIX_BUG_50
self.labels = self.findItems(data, media.Label)
diff --git a/lib/plexapi/const.py b/lib/plexapi/const.py
index 130555ad..bc3e81aa 100644
--- a/lib/plexapi/const.py
+++ b/lib/plexapi/const.py
@@ -3,7 +3,7 @@
# Library version
MAJOR_VERSION = 4
-MINOR_VERSION = 15
-PATCH_VERSION = 16
+MINOR_VERSION = 16
+PATCH_VERSION = 1
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
__version__ = f"{__short_version__}.{PATCH_VERSION}"
diff --git a/lib/plexapi/library.py b/lib/plexapi/library.py
index 6913b829..93801a1d 100644
--- a/lib/plexapi/library.py
+++ b/lib/plexapi/library.py
@@ -1740,7 +1740,7 @@ class LibrarySection(PlexObject):
def _edit(self, items=None, **kwargs):
""" Actually edit multiple objects. """
- if isinstance(self._edits, dict):
+ if isinstance(self._edits, dict) and items is None:
self._edits.update(kwargs)
return self
diff --git a/lib/plexapi/media.py b/lib/plexapi/media.py
index 2f76d722..9c6e3115 100644
--- a/lib/plexapi/media.py
+++ b/lib/plexapi/media.py
@@ -26,6 +26,7 @@ class Media(PlexObject):
height (int): The height of the media in pixels (ex: 256).
id (int): The unique ID for this media on the server.
has64bitOffsets (bool): True if video has 64 bit offsets.
+ hasVoiceActivity (bool): True if video has voice activity analyzed.
optimizedForStreaming (bool): True if video is optimized for streaming.
parts (List<:class:`~plexapi.media.MediaPart`>): List of media part objects.
proxyType (int): Equals 42 for optimized versions.
@@ -61,6 +62,7 @@ class Media(PlexObject):
self.height = utils.cast(int, data.attrib.get('height'))
self.id = utils.cast(int, data.attrib.get('id'))
self.has64bitOffsets = utils.cast(bool, data.attrib.get('has64bitOffsets'))
+ self.hasVoiceActivity = utils.cast(bool, data.attrib.get('hasVoiceActivity', '0'))
self.optimizedForStreaming = utils.cast(bool, data.attrib.get('optimizedForStreaming'))
self.parts = self.findItems(data, MediaPart)
self.proxyType = utils.cast(int, data.attrib.get('proxyType'))
@@ -441,6 +443,7 @@ class SubtitleStream(MediaPartStream):
Attributes:
TAG (str): 'Stream'
STREAMTYPE (int): 3
+ canAutoSync (bool): True if the subtitle stream can be auto synced.
container (str): The container of the subtitle stream.
forced (bool): True if this is a forced subtitle.
format (str): The format of the subtitle stream (ex: srt).
@@ -459,6 +462,7 @@ class SubtitleStream(MediaPartStream):
def _loadData(self, data):
""" Load attribute values from Plex XML response. """
super(SubtitleStream, self)._loadData(data)
+ self.canAutoSync = utils.cast(bool, data.attrib.get('canAutoSync'))
self.container = data.attrib.get('container')
self.forced = utils.cast(bool, data.attrib.get('forced', '0'))
self.format = data.attrib.get('format')
@@ -954,6 +958,26 @@ class Guid(PlexObject):
self.id = data.attrib.get('id')
+@utils.registerPlexObject
+class Image(PlexObject):
+ """ Represents a single Image media tag.
+
+ Attributes:
+ TAG (str): 'Image'
+ alt (str): The alt text for the image.
+ type (str): The type of image (e.g. coverPoster, background, snapshot).
+ url (str): The API URL (/library/metadata//thumb/).
+ """
+ TAG = 'Image'
+
+ def _loadData(self, data):
+ """ Load attribute values from Plex XML response. """
+ self._data = data
+ self.alt = data.attrib.get('alt')
+ self.type = data.attrib.get('type')
+ self.url = data.attrib.get('url')
+
+
@utils.registerPlexObject
class Rating(PlexObject):
""" Represents a single Rating media tag.
@@ -1074,6 +1098,11 @@ class Art(BaseResource):
TAG = 'Photo'
+class Logo(BaseResource):
+ """ Represents a single Logo object. """
+ TAG = 'Photo'
+
+
class Poster(BaseResource):
""" Represents a single Poster object. """
TAG = 'Photo'
diff --git a/lib/plexapi/mixins.py b/lib/plexapi/mixins.py
index bdf4607e..95f785fc 100644
--- a/lib/plexapi/mixins.py
+++ b/lib/plexapi/mixins.py
@@ -403,6 +403,63 @@ class ArtMixin(ArtUrlMixin, ArtLockMixin):
return self
+class LogoUrlMixin:
+ """ Mixin for Plex objects that can have a logo url. """
+
+ @property
+ def logoUrl(self):
+ """ Return the logo url for the Plex object. """
+ image = next((i for i in self.images if i.type == 'clearLogo'), None)
+ return self._server.url(image.url, includeToken=True) if image else None
+
+
+class LogoLockMixin:
+ """ Mixin for Plex objects that can have a locked logo. """
+
+ def lockLogo(self):
+ """ Lock the logo for a Plex object. """
+ raise NotImplementedError('Logo cannot be locked through the API.')
+
+ def unlockLogo(self):
+ """ Unlock the logo for a Plex object. """
+ raise NotImplementedError('Logo cannot be unlocked through the API.')
+
+
+class LogoMixin(LogoUrlMixin, LogoLockMixin):
+ """ Mixin for Plex objects that can have logos. """
+
+ def logos(self):
+ """ Returns list of available :class:`~plexapi.media.Logo` objects. """
+ return self.fetchItems(f'/library/metadata/{self.ratingKey}/clearLogos', cls=media.Logo)
+
+ def uploadLogo(self, url=None, filepath=None):
+ """ Upload a logo from a url or filepath.
+
+ Parameters:
+ url (str): The full URL to the image to upload.
+ filepath (str): The full file path the the image to upload or file-like object.
+ """
+ if url:
+ key = f'/library/metadata/{self.ratingKey}/clearLogos?url={quote_plus(url)}'
+ self._server.query(key, method=self._server._session.post)
+ elif filepath:
+ key = f'/library/metadata/{self.ratingKey}/clearLogos'
+ data = openOrRead(filepath)
+ self._server.query(key, method=self._server._session.post, data=data)
+ return self
+
+ def setLogo(self, logo):
+ """ Set the logo for a Plex object.
+
+ Raises:
+ :exc:`~plexapi.exceptions.NotImplementedError`: Logo cannot be set through the API.
+ """
+ raise NotImplementedError(
+ 'Logo cannot be set through the API. '
+ 'Re-upload the logo using "uploadLogo" to set it.'
+ )
+
+
class PosterUrlMixin:
""" Mixin for Plex objects that can have a poster url. """
@@ -513,6 +570,11 @@ class ThemeMixin(ThemeUrlMixin, ThemeLockMixin):
return self
def setTheme(self, theme):
+ """ Set the theme for a Plex object.
+
+ Raises:
+ :exc:`~plexapi.exceptions.NotImplementedError`: Themes cannot be set through the API.
+ """
raise NotImplementedError(
'Themes cannot be set through the API. '
'Re-upload the theme using "uploadTheme" to set it.'
diff --git a/lib/plexapi/myplex.py b/lib/plexapi/myplex.py
index 24e32e6b..448a2649 100644
--- a/lib/plexapi/myplex.py
+++ b/lib/plexapi/myplex.py
@@ -283,10 +283,10 @@ class MyPlexAccount(PlexObject):
""" Returns the :class:`~plexapi.myplex.MyPlexResource` that matches the name specified.
Parameters:
- name (str): Name to match against.
+ name (str): Name or machine identifier to match against.
"""
for resource in self.resources():
- if resource.name.lower() == name.lower():
+ if resource.name.lower() == name.lower() or resource.clientIdentifier == name:
return resource
raise NotFound(f'Unable to find resource {name}')
diff --git a/lib/plexapi/photo.py b/lib/plexapi/photo.py
index c68b3613..4347f31a 100644
--- a/lib/plexapi/photo.py
+++ b/lib/plexapi/photo.py
@@ -30,6 +30,7 @@ class Photoalbum(
composite (str): URL to composite image (/library/metadata//composite/)
fields (List<:class:`~plexapi.media.Field`>): List of field objects.
guid (str): Plex GUID for the photo album (local://229674).
+ images (List<:class:`~plexapi.media.Image`>): List of image objects.
index (sting): Plex index number for the photo album.
key (str): API URL (/library/metadata/).
lastRatedAt (datetime): Datetime the photo album was last rated.
@@ -57,6 +58,7 @@ class Photoalbum(
self.composite = data.attrib.get('composite')
self.fields = self.findItems(data, media.Field)
self.guid = data.attrib.get('guid')
+ self.images = self.findItems(data, media.Image)
self.index = utils.cast(int, data.attrib.get('index'))
self.key = data.attrib.get('key', '').replace('/children', '') # FIX_BUG_50
self.lastRatedAt = utils.toDatetime(data.attrib.get('lastRatedAt'))
@@ -164,6 +166,7 @@ class Photo(
createdAtTZOffset (int): Unknown (-25200).
fields (List<:class:`~plexapi.media.Field`>): List of field objects.
guid (str): Plex GUID for the photo (com.plexapp.agents.none://231714?lang=xn).
+ images (List<:class:`~plexapi.media.Image`>): List of image objects.
index (sting): Plex index number for the photo.
key (str): API URL (/library/metadata/).
lastRatedAt (datetime): Datetime the photo was last rated.
@@ -204,6 +207,7 @@ class Photo(
self.createdAtTZOffset = utils.cast(int, data.attrib.get('createdAtTZOffset'))
self.fields = self.findItems(data, media.Field)
self.guid = data.attrib.get('guid')
+ self.images = self.findItems(data, media.Image)
self.index = utils.cast(int, data.attrib.get('index'))
self.key = data.attrib.get('key', '')
self.lastRatedAt = utils.toDatetime(data.attrib.get('lastRatedAt'))
diff --git a/lib/plexapi/playlist.py b/lib/plexapi/playlist.py
index dda3bdf5..e2c4da63 100644
--- a/lib/plexapi/playlist.py
+++ b/lib/plexapi/playlist.py
@@ -190,6 +190,20 @@ class Playlist(
if self._items is None:
key = f'{self.key}/items'
items = self.fetchItems(key)
+
+ # Cache server connections to avoid reconnecting for each item
+ _servers = {}
+ for item in items:
+ if item.sourceURI:
+ serverID = item.sourceURI.split('/')[2]
+ if serverID not in _servers:
+ try:
+ _servers[serverID] = self._server.myPlexAccount().resource(serverID).connect()
+ except NotFound:
+ # Override the server connection with None if the server is not found
+ _servers[serverID] = None
+ item._server = _servers[serverID]
+
self._items = items
return self._items
diff --git a/lib/plexapi/sonos.py b/lib/plexapi/sonos.py
index 14f83d31..8f1295f4 100644
--- a/lib/plexapi/sonos.py
+++ b/lib/plexapi/sonos.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import requests
-from plexapi import CONFIG, X_PLEX_IDENTIFIER
+from plexapi import CONFIG, X_PLEX_IDENTIFIER, TIMEOUT
from plexapi.client import PlexClient
from plexapi.exceptions import BadRequest
from plexapi.playqueue import PlayQueue
@@ -46,7 +46,7 @@ class PlexSonosClient(PlexClient):
_session (obj): Requests session object used to access this client.
"""
- def __init__(self, account, data):
+ def __init__(self, account, data, timeout=None):
self._data = data
self.deviceClass = data.attrib.get("deviceClass")
self.machineIdentifier = data.attrib.get("machineIdentifier")
@@ -66,6 +66,7 @@ class PlexSonosClient(PlexClient):
self._last_call = 0
self._proxyThroughServer = False
self._showSecrets = CONFIG.get("log.show_secrets", "").lower() == "true"
+ self._timeout = timeout or TIMEOUT
def playMedia(self, media, offset=0, **params):
diff --git a/lib/plexapi/utils.py b/lib/plexapi/utils.py
index 549afc5b..dd1cfc9c 100644
--- a/lib/plexapi/utils.py
+++ b/lib/plexapi/utils.py
@@ -90,6 +90,8 @@ TAGTYPES = {
'theme': 317,
'studio': 318,
'network': 319,
+ 'showOrdering': 322,
+ 'clearLogo': 323,
'place': 400,
}
REVERSETAGTYPES = {v: k for k, v in TAGTYPES.items()}
diff --git a/lib/plexapi/video.py b/lib/plexapi/video.py
index 15755415..9e4201b8 100644
--- a/lib/plexapi/video.py
+++ b/lib/plexapi/video.py
@@ -9,7 +9,7 @@ from plexapi.base import Playable, PlexPartialObject, PlexHistory, PlexSession
from plexapi.exceptions import BadRequest
from plexapi.mixins import (
AdvancedSettingsMixin, SplitMergeMixin, UnmatchMatchMixin, ExtrasMixin, HubsMixin, PlayedUnplayedMixin, RatingMixin,
- ArtUrlMixin, ArtMixin, PosterUrlMixin, PosterMixin, ThemeUrlMixin, ThemeMixin,
+ ArtUrlMixin, ArtMixin, LogoMixin, PosterUrlMixin, PosterMixin, ThemeUrlMixin, ThemeMixin,
MovieEditMixins, ShowEditMixins, SeasonEditMixins, EpisodeEditMixins,
WatchlistMixin
)
@@ -26,6 +26,7 @@ class Video(PlexPartialObject, PlayedUnplayedMixin):
artBlurHash (str): BlurHash string for artwork image.
fields (List<:class:`~plexapi.media.Field`>): List of field objects.
guid (str): Plex GUID for the movie, show, season, episode, or clip (plex://movie/5d776b59ad5437001f79c6f8).
+ images (List<:class:`~plexapi.media.Image`>): List of image objects.
key (str): API URL (/library/metadata/).
lastRatedAt (datetime): Datetime the item was last rated.
lastViewedAt (datetime): Datetime the item was last played.
@@ -53,6 +54,7 @@ class Video(PlexPartialObject, PlayedUnplayedMixin):
self.artBlurHash = data.attrib.get('artBlurHash')
self.fields = self.findItems(data, media.Field)
self.guid = data.attrib.get('guid')
+ self.images = self.findItems(data, media.Image)
self.key = data.attrib.get('key', '')
self.lastRatedAt = utils.toDatetime(data.attrib.get('lastRatedAt'))
self.lastViewedAt = utils.toDatetime(data.attrib.get('lastViewedAt'))
@@ -332,7 +334,7 @@ class Video(PlexPartialObject, PlayedUnplayedMixin):
class Movie(
Video, Playable,
AdvancedSettingsMixin, SplitMergeMixin, UnmatchMatchMixin, ExtrasMixin, HubsMixin, RatingMixin,
- ArtMixin, PosterMixin, ThemeMixin,
+ ArtMixin, LogoMixin, PosterMixin, ThemeMixin,
MovieEditMixins,
WatchlistMixin
):
@@ -447,6 +449,11 @@ class Movie(
""" Returns True if the movie has a credits marker. """
return any(marker.type == 'credits' for marker in self.markers)
+ @property
+ def hasVoiceActivity(self):
+ """ Returns True if any of the media has voice activity analyzed. """
+ return any(media.hasVoiceActivity for media in self.media)
+
@property
def hasPreviewThumbnails(self):
""" Returns True if any of the media parts has generated preview (BIF) thumbnails. """
@@ -489,7 +496,7 @@ class Movie(
class Show(
Video,
AdvancedSettingsMixin, SplitMergeMixin, UnmatchMatchMixin, ExtrasMixin, HubsMixin, RatingMixin,
- ArtMixin, PosterMixin, ThemeMixin,
+ ArtMixin, LogoMixin, PosterMixin, ThemeMixin,
ShowEditMixins,
WatchlistMixin
):
@@ -709,7 +716,7 @@ class Show(
class Season(
Video,
AdvancedSettingsMixin, ExtrasMixin, RatingMixin,
- ArtMixin, PosterMixin, ThemeUrlMixin,
+ ArtMixin, LogoMixin, PosterMixin, ThemeUrlMixin,
SeasonEditMixins
):
""" Represents a single Season.
@@ -876,7 +883,7 @@ class Season(
class Episode(
Video, Playable,
ExtrasMixin, RatingMixin,
- ArtMixin, PosterMixin, ThemeUrlMixin,
+ ArtMixin, LogoMixin, PosterMixin, ThemeUrlMixin,
EpisodeEditMixins
):
""" Represents a single Episode.
@@ -1077,6 +1084,11 @@ class Episode(
""" Returns True if the episode has a credits marker. """
return any(marker.type == 'credits' for marker in self.markers)
+ @property
+ def hasVoiceActivity(self):
+ """ Returns True if any of the media has voice activity analyzed. """
+ return any(media.hasVoiceActivity for media in self.media)
+
@property
def hasPreviewThumbnails(self):
""" Returns True if any of the media parts has generated preview (BIF) thumbnails. """
diff --git a/lib/profilehooks.py b/lib/profilehooks.py
index 14ac6020..64c34382 100644
--- a/lib/profilehooks.py
+++ b/lib/profilehooks.py
@@ -39,28 +39,12 @@ instead of a detailed (but costly) profile.
Caveats
- A thread on python-dev convinced me that hotshot produces bogus numbers.
- See https://mail.python.org/pipermail/python-dev/2005-November/058264.html
-
I don't know what will happen if a decorated function will try to call
another decorated function. All decorators probably need to explicitly
support nested profiling (currently TraceFuncCoverage is the only one
- that supports this, while HotShotFuncProfile has support for recursive
- functions.)
+ that supports this.)
- Profiling with hotshot creates temporary files (*.prof for profiling,
- *.cprof for coverage) in the current directory. These files are not
- cleaned up. Exception: when you specify a filename to the profile
- decorator (to store the pstats.Stats object for later inspection),
- the temporary file will be the filename you specified with '.raw'
- appended at the end.
-
- Coverage analysis with hotshot seems to miss some executions resulting
- in lower line counts and some lines errorneously marked as never
- executed. For this reason coverage analysis now uses trace.py which is
- slower, but more accurate.
-
-Copyright (c) 2004--2020 Marius Gedminas
+Copyright (c) 2004--2023 Marius Gedminas
Copyright (c) 2007 Hanno Schlichting
Copyright (c) 2008 Florian Schulze
@@ -86,47 +70,21 @@ Released under the MIT licence since December 2006:
(Previously it was distributed under the GNU General Public Licence.)
"""
-from __future__ import print_function
-
-__author__ = "Marius Gedminas "
-__copyright__ = "Copyright 2004-2020 Marius Gedminas and contributors"
-__license__ = "MIT"
-__version__ = '1.12.0'
-__date__ = "2020-08-20"
-
import atexit
-
+import dis
import functools
import inspect
import logging
import os
+import pstats
import re
import sys
-
-# For profiling
-from profile import Profile
-import pstats
-
-# For timecall
import timeit
-
-# For hotshot profiling (inaccurate!)
-try:
- import hotshot
- import hotshot.stats
-except ImportError:
- hotshot = None
-
-# For trace.py coverage
-import trace
-import dis
import token
import tokenize
+import trace
+from profile import Profile
-# For hotshot coverage (inaccurate!; uses undocumented APIs; might break)
-if hotshot is not None:
- import _hotshot
- import hotshot.log
# For cProfile profiling (best)
try:
@@ -134,28 +92,22 @@ try:
except ImportError:
cProfile = None
+
+__author__ = "Marius Gedminas "
+__copyright__ = "Copyright 2004-2020 Marius Gedminas and contributors"
+__license__ = "MIT"
+__version__ = '1.13.0'
+__date__ = "2024-10-09"
+
+
# registry of available profilers
AVAILABLE_PROFILERS = {}
-__all__ = ['coverage', 'coverage_with_hotshot', 'profile', 'timecall']
-
-
-# Use tokenize.open() on Python >= 3.2, fall back to open() on Python 2
-tokenize_open = getattr(tokenize, 'open', open)
-
-
-def _unwrap(fn):
- # inspect.unwrap() doesn't exist on Python 2
- if not hasattr(fn, '__wrapped__'):
- return fn
- else:
- # intentionally using recursion here instead of a while loop to
- # make cycles fail with a recursion error instead of looping forever.
- return _unwrap(fn.__wrapped__)
+__all__ = ['coverage', 'profile', 'timecall']
def _identify(fn):
- fn = _unwrap(fn)
+ fn = inspect.unwrap(fn)
funcname = fn.__name__
filename = fn.__code__.co_filename
lineno = fn.__code__.co_firstlineno
@@ -168,7 +120,7 @@ def _is_file_like(o):
def profile(fn=None, skip=0, filename=None, immediate=False, dirs=False,
sort=None, entries=40,
- profiler=('cProfile', 'profile', 'hotshot'),
+ profiler=('cProfile', 'profile'),
stdout=True):
"""Mark `fn` for profiling.
@@ -205,7 +157,7 @@ def profile(fn=None, skip=0, filename=None, immediate=False, dirs=False,
`profiler` can be used to select the preferred profiler, or specify a
sequence of them, in order of preference. The default is ('cProfile'.
- 'profile', 'hotshot').
+ 'profile').
If `filename` is specified, the profile stats will be stored in the
named file. You can load them with pstats.Stats(filename) or use a
@@ -279,26 +231,7 @@ def coverage(fn):
...
"""
- fp = TraceFuncCoverage(fn) # or HotShotFuncCoverage
- # We cannot return fp or fp.__call__ directly as that would break method
- # definitions, instead we need to return a plain function.
-
- @functools.wraps(fn)
- def new_fn(*args, **kw):
- return fp(*args, **kw)
- return new_fn
-
-
-def coverage_with_hotshot(fn):
- """Mark `fn` for line coverage analysis.
-
- Uses the 'hotshot' module for fast coverage analysis.
-
- BUG: Produces inaccurate results.
-
- See the docstring of `coverage` for usage examples.
- """
- fp = HotShotFuncCoverage(fn)
+ fp = TraceFuncCoverage(fn)
# We cannot return fp or fp.__call__ directly as that would break method
# definitions, instead we need to return a plain function.
@@ -424,148 +357,8 @@ if cProfile is not None:
AVAILABLE_PROFILERS['cProfile'] = CProfileFuncProfile
-if hotshot is not None:
-
- class HotShotFuncProfile(FuncProfile):
- """Profiler for a function (uses hotshot)."""
-
- # This flag is shared between all instances
- in_profiler = False
-
- def __init__(self, fn, skip=0, filename=None, immediate=False,
- dirs=False, sort=None, entries=40, stdout=True):
- """Creates a profiler for a function.
-
- Every profiler has its own log file (the name of which is derived
- from the function name).
-
- HotShotFuncProfile registers an atexit handler that prints
- profiling information to sys.stderr when the program terminates.
-
- The log file is not removed and remains there to clutter the
- current working directory.
- """
- if filename:
- self.logfilename = filename + ".raw"
- else:
- self.logfilename = "%s.%d.prof" % (fn.__name__, os.getpid())
- super(HotShotFuncProfile, self).__init__(
- fn, skip=skip, filename=filename, immediate=immediate,
- dirs=dirs, sort=sort, entries=entries, stdout=stdout)
-
- def __call__(self, *args, **kw):
- """Profile a singe call to the function."""
- self.ncalls += 1
- if self.skip > 0:
- self.skip -= 1
- self.skipped += 1
- return self.fn(*args, **kw)
- if HotShotFuncProfile.in_profiler:
- # handle recursive calls
- return self.fn(*args, **kw)
- if self.profiler is None:
- self.profiler = hotshot.Profile(self.logfilename)
- try:
- HotShotFuncProfile.in_profiler = True
- return self.profiler.runcall(self.fn, *args, **kw)
- finally:
- HotShotFuncProfile.in_profiler = False
- if self.immediate:
- self.print_stats()
- self.reset_stats()
-
- def print_stats(self):
- if self.profiler is None:
- self.stats = pstats.Stats(Profile())
- else:
- self.profiler.close()
- self.stats = hotshot.stats.load(self.logfilename)
- super(HotShotFuncProfile, self).print_stats()
-
- def reset_stats(self):
- self.profiler = None
- self.ncalls = 0
- self.skipped = 0
-
- AVAILABLE_PROFILERS['hotshot'] = HotShotFuncProfile
-
- class HotShotFuncCoverage:
- """Coverage analysis for a function (uses _hotshot).
-
- HotShot coverage is reportedly faster than trace.py, but it appears to
- have problems with exceptions; also line counts in coverage reports
- are generally lower from line counts produced by TraceFuncCoverage.
- Is this my bug, or is it a problem with _hotshot?
- """
-
- def __init__(self, fn):
- """Creates a profiler for a function.
-
- Every profiler has its own log file (the name of which is derived
- from the function name).
-
- HotShotFuncCoverage registers an atexit handler that prints
- profiling information to sys.stderr when the program terminates.
-
- The log file is not removed and remains there to clutter the
- current working directory.
- """
- self.fn = fn
- self.logfilename = "%s.%d.cprof" % (fn.__name__, os.getpid())
- self.profiler = _hotshot.coverage(self.logfilename)
- self.ncalls = 0
- atexit.register(self.atexit)
-
- def __call__(self, *args, **kw):
- """Profile a singe call to the function."""
- self.ncalls += 1
- old_trace = sys.gettrace()
- try:
- return self.profiler.runcall(self.fn, args, kw)
- finally: # pragma: nocover
- sys.settrace(old_trace)
-
- def atexit(self):
- """Stop profiling and print profile information to sys.stderr.
-
- This function is registered as an atexit hook.
- """
- self.profiler.close()
- funcname, filename, lineno = _identify(self.fn)
- print("")
- print("*** COVERAGE RESULTS ***")
- print("%s (%s:%s)" % (funcname, filename, lineno))
- print("function called %d times" % self.ncalls)
- print("")
- fs = FuncSource(self.fn)
- reader = hotshot.log.LogReader(self.logfilename)
- for what, (filename, lineno, funcname), tdelta in reader:
- if filename != fs.filename:
- continue
- if what == hotshot.log.LINE:
- fs.mark(lineno)
- if what == hotshot.log.ENTER:
- # hotshot gives us the line number of the function
- # definition and never gives us a LINE event for the first
- # statement in a function, so if we didn't perform this
- # mapping, the first statement would be marked as never
- # executed
- if lineno == fs.firstlineno:
- lineno = fs.firstcodelineno
- fs.mark(lineno)
- reader.close()
- print(fs)
- never_executed = fs.count_never_executed()
- if never_executed:
- print("%d lines were not executed." % never_executed)
-
-
class TraceFuncCoverage:
- """Coverage analysis for a function (uses trace module).
-
- HotShot coverage analysis is reportedly faster, but it appears to have
- problems with exceptions.
- """
+ """Coverage analysis for a function (uses trace module)."""
# Shared between all instances so that nested calls work
tracer = trace.Trace(count=True, trace=False,
@@ -646,13 +439,19 @@ class FuncSource:
def find_source_lines(self):
"""Mark all executable source lines in fn as executed 0 times."""
- if self.filename is None:
+ if self.filename is None: # pragma: nocover
+ # I don't know how to make inspect.getsourcefile() return None in
+ # our test suite, but I've looked at its source and I know that it
+ # can do so.
return
strs = self._find_docstrings(self.filename)
lines = {
ln
- for off, ln in dis.findlinestarts(_unwrap(self.fn).__code__)
- if ln not in strs
+ for off, ln in dis.findlinestarts(inspect.unwrap(self.fn).__code__)
+ # skipping firstlineno because Python 3.11 adds a 'RESUME' opcode
+ # attributed to the `def` line, but then trace.py never sees it
+ # getting executed
+ if ln is not None and ln not in strs and ln != self.firstlineno
}
for lineno in lines:
self.sourcelines.setdefault(lineno, 0)
@@ -667,7 +466,7 @@ class FuncSource:
# Python 3.2 and removed in 3.6.
strs = set()
prev = token.INDENT # so module docstring is detected as docstring
- with tokenize_open(filename) as f:
+ with tokenize.open(filename) as f:
tokens = tokenize.generate_tokens(f.readline)
for ttype, tstr, start, end, line in tokens:
if ttype == token.STRING and prev == token.INDENT:
diff --git a/lib/pyparsing/__init__.py b/lib/pyparsing/__init__.py
index 79d8153c..543ceb62 100644
--- a/lib/pyparsing/__init__.py
+++ b/lib/pyparsing/__init__.py
@@ -120,8 +120,8 @@ class version_info(NamedTuple):
return f"{__name__}.{type(self).__name__}({', '.join('{}={!r}'.format(*nv) for nv in zip(self._fields, self))})"
-__version_info__ = version_info(3, 1, 2, "final", 1)
-__version_time__ = "06 Mar 2024 07:08 UTC"
+__version_info__ = version_info(3, 2, 0, "final", 1)
+__version_time__ = "13 Oct 2024 09:46 UTC"
__version__ = __version_info__.__version__
__versionTime__ = __version_time__
__author__ = "Paul McGuire "
@@ -131,9 +131,9 @@ from .exceptions import *
from .actions import *
from .core import __diag__, __compat__
from .results import *
-from .core import * # type: ignore[misc, assignment]
+from .core import *
from .core import _builtin_exprs as core_builtin_exprs
-from .helpers import * # type: ignore[misc, assignment]
+from .helpers import *
from .helpers import _builtin_exprs as helper_builtin_exprs
from .unicode import unicode_set, UnicodeRangeList, pyparsing_unicode as unicode
@@ -143,13 +143,13 @@ from .common import (
_builtin_exprs as common_builtin_exprs,
)
-# define backward compat synonyms
+# Compatibility synonyms
if "pyparsing_unicode" not in globals():
pyparsing_unicode = unicode # type: ignore[misc]
if "pyparsing_common" not in globals():
- pyparsing_common = common # type: ignore[misc]
+ pyparsing_common = common
if "pyparsing_test" not in globals():
- pyparsing_test = testing # type: ignore[misc]
+ pyparsing_test = testing
core_builtin_exprs += common_builtin_exprs + helper_builtin_exprs
@@ -208,6 +208,7 @@ __all__ = [
"StringEnd",
"StringStart",
"Suppress",
+ "Tag",
"Token",
"TokenConverter",
"White",
diff --git a/lib/pyparsing/actions.py b/lib/pyparsing/actions.py
index ce51b395..1d2dce99 100644
--- a/lib/pyparsing/actions.py
+++ b/lib/pyparsing/actions.py
@@ -196,7 +196,7 @@ def with_class(classname, namespace=""):
return with_attribute(**{classattr: classname})
-# pre-PEP8 compatibility symbols
+# Compatibility synonyms
# fmt: off
replaceWith = replaced_by_pep8("replaceWith", replace_with)
removeQuotes = replaced_by_pep8("removeQuotes", remove_quotes)
diff --git a/lib/pyparsing/common.py b/lib/pyparsing/common.py
index 74faa460..649aad00 100644
--- a/lib/pyparsing/common.py
+++ b/lib/pyparsing/common.py
@@ -418,20 +418,15 @@ class pyparsing_common:
# fmt: on
# pre-PEP8 compatibility names
- convertToInteger = convert_to_integer
- """Deprecated - use :class:`convert_to_integer`"""
- convertToFloat = convert_to_float
- """Deprecated - use :class:`convert_to_float`"""
- convertToDate = convert_to_date
- """Deprecated - use :class:`convert_to_date`"""
- convertToDatetime = convert_to_datetime
- """Deprecated - use :class:`convert_to_datetime`"""
- stripHTMLTags = strip_html_tags
- """Deprecated - use :class:`strip_html_tags`"""
- upcaseTokens = upcase_tokens
- """Deprecated - use :class:`upcase_tokens`"""
- downcaseTokens = downcase_tokens
- """Deprecated - use :class:`downcase_tokens`"""
+ # fmt: off
+ convertToInteger = staticmethod(replaced_by_pep8("convertToInteger", convert_to_integer))
+ convertToFloat = staticmethod(replaced_by_pep8("convertToFloat", convert_to_float))
+ convertToDate = staticmethod(replaced_by_pep8("convertToDate", convert_to_date))
+ convertToDatetime = staticmethod(replaced_by_pep8("convertToDatetime", convert_to_datetime))
+ stripHTMLTags = staticmethod(replaced_by_pep8("stripHTMLTags", strip_html_tags))
+ upcaseTokens = staticmethod(replaced_by_pep8("upcaseTokens", upcase_tokens))
+ downcaseTokens = staticmethod(replaced_by_pep8("downcaseTokens", downcase_tokens))
+ # fmt: on
_builtin_exprs = [
diff --git a/lib/pyparsing/core.py b/lib/pyparsing/core.py
index b19d1221..4f43c3bf 100644
--- a/lib/pyparsing/core.py
+++ b/lib/pyparsing/core.py
@@ -1,7 +1,9 @@
#
# core.py
#
+from __future__ import annotations
+import collections.abc
from collections import deque
import os
import typing
@@ -9,12 +11,9 @@ from typing import (
Any,
Callable,
Generator,
- List,
NamedTuple,
Sequence,
- Set,
TextIO,
- Tuple,
Union,
cast,
)
@@ -51,7 +50,7 @@ from .results import ParseResults, _ParseResultsWithOffset
from .unicode import pyparsing_unicode
_MAX_INT = sys.maxsize
-str_type: Tuple[type, ...] = (str, bytes)
+str_type: tuple[type, ...] = (str, bytes)
#
# Copyright (c) 2003-2022 Paul T. McGuire
@@ -76,18 +75,7 @@ str_type: Tuple[type, ...] = (str, bytes)
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
-
-if sys.version_info >= (3, 8):
- from functools import cached_property
-else:
-
- class cached_property:
- def __init__(self, func):
- self._func = func
-
- def __get__(self, instance, owner=None):
- ret = instance.__dict__[self._func.__name__] = self._func(instance)
- return ret
+from functools import cached_property
class __compat__(__config_flags):
@@ -218,22 +206,14 @@ if _should_enable_warnings(
# build list of single arg builtins, that can be used as parse actions
+# fmt: off
_single_arg_builtins = {
- sum,
- len,
- sorted,
- reversed,
- list,
- tuple,
- set,
- any,
- all,
- min,
- max,
+ sum, len, sorted, reversed, list, tuple, set, any, all, min, max
}
+# fmt: on
_generatorType = types.GeneratorType
-ParseImplReturnType = Tuple[int, Any]
+ParseImplReturnType = tuple[int, Any]
PostParseReturnType = Union[ParseResults, Sequence[ParseResults]]
ParseAction = Union[
Callable[[], Any],
@@ -255,20 +235,34 @@ DebugSuccessAction = Callable[
DebugExceptionAction = Callable[[str, int, "ParserElement", Exception, bool], None]
-alphas = string.ascii_uppercase + string.ascii_lowercase
-identchars = pyparsing_unicode.Latin1.identchars
-identbodychars = pyparsing_unicode.Latin1.identbodychars
-nums = "0123456789"
-hexnums = nums + "ABCDEFabcdef"
-alphanums = alphas + nums
-printables = "".join([c for c in string.printable if c not in string.whitespace])
+alphas: str = string.ascii_uppercase + string.ascii_lowercase
+identchars: str = pyparsing_unicode.Latin1.identchars
+identbodychars: str = pyparsing_unicode.Latin1.identbodychars
+nums: str = "0123456789"
+hexnums: str = nums + "ABCDEFabcdef"
+alphanums: str = alphas + nums
+printables: str = "".join([c for c in string.printable if c not in string.whitespace])
+
+
+class _ParseActionIndexError(Exception):
+ """
+ Internal wrapper around IndexError so that IndexErrors raised inside
+ parse actions aren't misinterpreted as IndexErrors raised inside
+ ParserElement parseImpl methods.
+ """
+
+ def __init__(self, msg: str, exc: BaseException):
+ self.msg: str = msg
+ self.exc: BaseException = exc
+
_trim_arity_call_line: traceback.StackSummary = None # type: ignore[assignment]
+pa_call_line_synth = ()
def _trim_arity(func, max_limit=3):
"""decorator to trim function calls to match the arity of the target"""
- global _trim_arity_call_line
+ global _trim_arity_call_line, pa_call_line_synth
if func in _single_arg_builtins:
return lambda s, l, t: func(t)
@@ -280,14 +274,16 @@ def _trim_arity(func, max_limit=3):
# user's parse action 'func', so that we don't incur call penalty at parse time
# fmt: off
- LINE_DIFF = 7
+ LINE_DIFF = 9
# IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND
# THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!!
- _trim_arity_call_line = (_trim_arity_call_line or traceback.extract_stack(limit=2)[-1])
- pa_call_line_synth = (_trim_arity_call_line[0], _trim_arity_call_line[1] + LINE_DIFF)
+ _trim_arity_call_line = _trim_arity_call_line or traceback.extract_stack(limit=2)[-1]
+ pa_call_line_synth = pa_call_line_synth or (_trim_arity_call_line[0], _trim_arity_call_line[1] + LINE_DIFF)
def wrapper(*args):
nonlocal found_arity, limit
+ if found_arity:
+ return func(*args[limit:])
while 1:
try:
ret = func(*args[limit:])
@@ -312,6 +308,11 @@ def _trim_arity(func, max_limit=3):
continue
raise
+ except IndexError as ie:
+ # wrap IndexErrors inside a _ParseActionIndexError
+ raise _ParseActionIndexError(
+ "IndexError raised in parse action", ie
+ ).with_traceback(None)
# fmt: on
# copy func name to wrapper for sensible debug output
@@ -352,7 +353,7 @@ def condition_as_parse_action(
def _default_start_debug_action(
- instring: str, loc: int, expr: "ParserElement", cache_hit: bool = False
+ instring: str, loc: int, expr: ParserElement, cache_hit: bool = False
):
cache_hit_str = "*" if cache_hit else ""
print(
@@ -368,7 +369,7 @@ def _default_success_debug_action(
instring: str,
startloc: int,
endloc: int,
- expr: "ParserElement",
+ expr: ParserElement,
toks: ParseResults,
cache_hit: bool = False,
):
@@ -379,7 +380,7 @@ def _default_success_debug_action(
def _default_exception_debug_action(
instring: str,
loc: int,
- expr: "ParserElement",
+ expr: ParserElement,
exc: Exception,
cache_hit: bool = False,
):
@@ -444,7 +445,7 @@ class ParserElement(ABC):
@classmethod
def using_each(cls, seq, **class_kwargs):
"""
- Yields a sequence of class(obj, **class_kwargs) for obj in seq.
+ Yields a sequence of ``class(obj, **class_kwargs)`` for obj in seq.
Example::
@@ -459,7 +460,7 @@ class ParserElement(ABC):
debug_fail: typing.Optional[DebugExceptionAction]
def __init__(self, savelist: bool = False):
- self.parseAction: List[ParseAction] = list()
+ self.parseAction: list[ParseAction] = list()
self.failAction: typing.Optional[ParseFailAction] = None
self.customName: str = None # type: ignore[assignment]
self._defaultName: typing.Optional[str] = None
@@ -471,12 +472,12 @@ class ParserElement(ABC):
# used when checking for left-recursion
self.mayReturnEmpty = False
self.keepTabs = False
- self.ignoreExprs: List["ParserElement"] = list()
+ self.ignoreExprs: list[ParserElement] = list()
self.debug = False
self.streamlined = False
# optimize exception handling for subclasses that don't advance parse index
self.mayIndexError = True
- self.errmsg = ""
+ self.errmsg: Union[str, None] = ""
# mark results names as modal (report only last) or cumulative (list all)
self.modalResults = True
# custom debug actions
@@ -484,9 +485,9 @@ class ParserElement(ABC):
# avoid redundant calls to preParse
self.callPreparse = True
self.callDuringTry = False
- self.suppress_warnings_: List[Diagnostics] = []
+ self.suppress_warnings_: list[Diagnostics] = []
- def suppress_warning(self, warning_type: Diagnostics) -> "ParserElement":
+ def suppress_warning(self, warning_type: Diagnostics) -> ParserElement:
"""
Suppress warnings emitted for a particular diagnostic on this expression.
@@ -519,7 +520,7 @@ class ParserElement(ABC):
to_visit.extend(cur.recurse())
yield cur
- def copy(self) -> "ParserElement":
+ def copy(self) -> ParserElement:
"""
Make a copy of this :class:`ParserElement`. Useful for defining
different parse actions for the same parsing pattern, using copies of
@@ -550,7 +551,7 @@ class ParserElement(ABC):
def set_results_name(
self, name: str, list_all_matches: bool = False, *, listAllMatches: bool = False
- ) -> "ParserElement":
+ ) -> ParserElement:
"""
Define name for referencing matching tokens as a nested attribute
of the returned parse results.
@@ -582,18 +583,18 @@ class ParserElement(ABC):
listAllMatches = listAllMatches or list_all_matches
return self._setResultsName(name, listAllMatches)
- def _setResultsName(self, name, listAllMatches=False):
+ def _setResultsName(self, name, list_all_matches=False) -> ParserElement:
if name is None:
return self
newself = self.copy()
if name.endswith("*"):
name = name[:-1]
- listAllMatches = True
+ list_all_matches = True
newself.resultsName = name
- newself.modalResults = not listAllMatches
+ newself.modalResults = not list_all_matches
return newself
- def set_break(self, break_flag: bool = True) -> "ParserElement":
+ def set_break(self, break_flag: bool = True) -> ParserElement:
"""
Method to invoke the Python pdb debugger when this element is
about to be parsed. Set ``break_flag`` to ``True`` to enable, ``False`` to
@@ -602,20 +603,18 @@ class ParserElement(ABC):
if break_flag:
_parseMethod = self._parse
- def breaker(instring, loc, doActions=True, callPreParse=True):
- import pdb
-
- # this call to pdb.set_trace() is intentional, not a checkin error
- pdb.set_trace()
- return _parseMethod(instring, loc, doActions, callPreParse)
+ def breaker(instring, loc, do_actions=True, callPreParse=True):
+ # this call to breakpoint() is intentional, not a checkin error
+ breakpoint()
+ return _parseMethod(instring, loc, do_actions, callPreParse)
breaker._originalParseMethod = _parseMethod # type: ignore [attr-defined]
- self._parse = breaker # type: ignore [assignment]
+ self._parse = breaker # type: ignore [method-assign]
elif hasattr(self._parse, "_originalParseMethod"):
- self._parse = self._parse._originalParseMethod # type: ignore [attr-defined, assignment]
+ self._parse = self._parse._originalParseMethod # type: ignore [method-assign]
return self
- def set_parse_action(self, *fns: ParseAction, **kwargs) -> "ParserElement":
+ def set_parse_action(self, *fns: ParseAction, **kwargs: Any) -> ParserElement:
"""
Define one or more actions to perform when successfully matching parse element definition.
@@ -691,19 +690,19 @@ class ParserElement(ABC):
''')
"""
if list(fns) == [None]:
- self.parseAction = []
+ self.parseAction.clear()
return self
if not all(callable(fn) for fn in fns):
raise TypeError("parse actions must be callable")
- self.parseAction = [_trim_arity(fn) for fn in fns]
+ self.parseAction[:] = [_trim_arity(fn) for fn in fns]
self.callDuringTry = kwargs.get(
"call_during_try", kwargs.get("callDuringTry", False)
)
return self
- def add_parse_action(self, *fns: ParseAction, **kwargs) -> "ParserElement":
+ def add_parse_action(self, *fns: ParseAction, **kwargs: Any) -> ParserElement:
"""
Add one or more parse actions to expression's list of parse actions. See :class:`set_parse_action`.
@@ -715,7 +714,7 @@ class ParserElement(ABC):
)
return self
- def add_condition(self, *fns: ParseCondition, **kwargs) -> "ParserElement":
+ def add_condition(self, *fns: ParseCondition, **kwargs: Any) -> ParserElement:
"""Add a boolean predicate function to expression's list of parse actions. See
:class:`set_parse_action` for function call signatures. Unlike ``set_parse_action``,
functions passed to ``add_condition`` need to return boolean success/fail of the condition.
@@ -752,7 +751,7 @@ class ParserElement(ABC):
)
return self
- def set_fail_action(self, fn: ParseFailAction) -> "ParserElement":
+ def set_fail_action(self, fn: ParseFailAction) -> ParserElement:
"""
Define action to perform if parsing fails at this expression.
Fail acton fn is a callable function that takes the arguments
@@ -801,7 +800,7 @@ class ParserElement(ABC):
return loc
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
return loc, []
def postParse(self, instring, loc, tokenlist):
@@ -809,10 +808,9 @@ class ParserElement(ABC):
# @profile
def _parseNoCache(
- self, instring, loc, doActions=True, callPreParse=True
- ) -> Tuple[int, ParseResults]:
- TRY, MATCH, FAIL = 0, 1, 2
- debugging = self.debug # and doActions)
+ self, instring, loc, do_actions=True, callPreParse=True
+ ) -> tuple[int, ParseResults]:
+ debugging = self.debug # and do_actions)
len_instring = len(instring)
if debugging or self.failAction:
@@ -827,11 +825,11 @@ class ParserElement(ABC):
self.debugActions.debug_try(instring, tokens_start, self, False)
if self.mayIndexError or pre_loc >= len_instring:
try:
- loc, tokens = self.parseImpl(instring, pre_loc, doActions)
+ loc, tokens = self.parseImpl(instring, pre_loc, do_actions)
except IndexError:
raise ParseException(instring, len_instring, self.errmsg, self)
else:
- loc, tokens = self.parseImpl(instring, pre_loc, doActions)
+ loc, tokens = self.parseImpl(instring, pre_loc, do_actions)
except Exception as err:
# print("Exception raised:", err)
if self.debugActions.debug_fail:
@@ -849,18 +847,18 @@ class ParserElement(ABC):
tokens_start = pre_loc
if self.mayIndexError or pre_loc >= len_instring:
try:
- loc, tokens = self.parseImpl(instring, pre_loc, doActions)
+ loc, tokens = self.parseImpl(instring, pre_loc, do_actions)
except IndexError:
raise ParseException(instring, len_instring, self.errmsg, self)
else:
- loc, tokens = self.parseImpl(instring, pre_loc, doActions)
+ loc, tokens = self.parseImpl(instring, pre_loc, do_actions)
tokens = self.postParse(instring, loc, tokens)
ret_tokens = ParseResults(
tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults
)
- if self.parseAction and (doActions or self.callDuringTry):
+ if self.parseAction and (do_actions or self.callDuringTry):
if debugging:
try:
for fn in self.parseAction:
@@ -919,7 +917,7 @@ class ParserElement(ABC):
do_actions: bool = False,
) -> int:
try:
- return self._parse(instring, loc, doActions=do_actions)[0]
+ return self._parse(instring, loc, do_actions=do_actions)[0]
except ParseFatalException:
if raise_fatal:
raise
@@ -935,43 +933,59 @@ class ParserElement(ABC):
# cache for left-recursion in Forward references
recursion_lock = RLock()
- recursion_memos: typing.Dict[
- Tuple[int, "Forward", bool], Tuple[int, Union[ParseResults, Exception]]
+ recursion_memos: collections.abc.MutableMapping[
+ tuple[int, Forward, bool], tuple[int, Union[ParseResults, Exception]]
] = {}
- class _CacheType(dict):
+ class _CacheType(typing.Protocol):
"""
- class to help type checking
+ Class to be used for packrat and left-recursion cacheing of results
+ and exceptions.
"""
not_in_cache: bool
- def get(self, *args): ...
+ def get(self, *args) -> typing.Any: ...
- def set(self, *args): ...
+ def set(self, *args) -> None: ...
- # argument cache for optimizing repeated calls when backtracking through recursive expressions
- packrat_cache = (
- _CacheType()
- ) # set later by enable_packrat(); this is here so that reset_cache() doesn't fail
+ def clear(self) -> None: ...
+
+ class NullCache(dict):
+ """
+ A null cache type for initialization of the packrat_cache class variable.
+ If/when enable_packrat() is called, this null cache will be replaced by a
+ proper _CacheType class instance.
+ """
+
+ not_in_cache: bool = True
+
+ def get(self, *args) -> typing.Any: ...
+
+ def set(self, *args) -> None: ...
+
+ def clear(self) -> None: ...
+
+ # class-level argument cache for optimizing repeated calls when backtracking
+ # through recursive expressions
+ packrat_cache: _CacheType = NullCache()
packrat_cache_lock = RLock()
packrat_cache_stats = [0, 0]
# this method gets repeatedly called during backtracking with the same arguments -
# we can cache these arguments and save ourselves the trouble of re-parsing the contained expression
def _parseCache(
- self, instring, loc, doActions=True, callPreParse=True
- ) -> Tuple[int, ParseResults]:
+ self, instring, loc, do_actions=True, callPreParse=True
+ ) -> tuple[int, ParseResults]:
HIT, MISS = 0, 1
- TRY, MATCH, FAIL = 0, 1, 2
- lookup = (self, instring, loc, callPreParse, doActions)
+ lookup = (self, instring, loc, callPreParse, do_actions)
with ParserElement.packrat_cache_lock:
cache = ParserElement.packrat_cache
value = cache.get(lookup)
if value is cache.not_in_cache:
ParserElement.packrat_cache_stats[MISS] += 1
try:
- value = self._parseNoCache(instring, loc, doActions, callPreParse)
+ value = self._parseNoCache(instring, loc, do_actions, callPreParse)
except ParseBaseException as pe:
# cache a copy of the exception, without the traceback
cache.set(lookup, pe.__class__(*pe.args))
@@ -996,7 +1010,7 @@ class ParserElement(ABC):
pass
raise value
- value = cast(Tuple[int, ParseResults, int], value)
+ value = cast(tuple[int, ParseResults, int], value)
loc_, result, endloc = value[0], value[1].copy(), value[2]
if self.debug and self.debugActions.debug_match:
try:
@@ -1076,7 +1090,7 @@ class ParserElement(ABC):
elif ParserElement._packratEnabled:
raise RuntimeError("Packrat and Bounded Recursion are not compatible")
if cache_size_limit is None:
- ParserElement.recursion_memos = _UnboundedMemo() # type: ignore[assignment]
+ ParserElement.recursion_memos = _UnboundedMemo()
elif cache_size_limit > 0:
ParserElement.recursion_memos = _LRUMemo(capacity=cache_size_limit) # type: ignore[assignment]
else:
@@ -1129,7 +1143,7 @@ class ParserElement(ABC):
if cache_size_limit is None:
ParserElement.packrat_cache = _UnboundedCache()
else:
- ParserElement.packrat_cache = _FifoCache(cache_size_limit) # type: ignore[assignment]
+ ParserElement.packrat_cache = _FifoCache(cache_size_limit)
ParserElement._parse = ParserElement._parseCache
def parse_string(
@@ -1190,14 +1204,16 @@ class ParserElement(ABC):
loc, tokens = self._parse(instring, 0)
if parseAll:
loc = self.preParse(instring, loc)
- se = Empty() + StringEnd()
+ se = Empty() + StringEnd().set_debug(False)
se._parse(instring, loc)
+ except _ParseActionIndexError as pa_exc:
+ raise pa_exc.exc
except ParseBaseException as exc:
if ParserElement.verbose_stacktrace:
raise
- else:
- # catch and re-raise exception from here, clearing out pyparsing internal stack trace
- raise exc.with_traceback(None)
+
+ # catch and re-raise exception from here, clearing out pyparsing internal stack trace
+ raise exc.with_traceback(None)
else:
return tokens
@@ -1206,10 +1222,11 @@ class ParserElement(ABC):
instring: str,
max_matches: int = _MAX_INT,
overlap: bool = False,
+ always_skip_whitespace=True,
*,
debug: bool = False,
maxMatches: int = _MAX_INT,
- ) -> Generator[Tuple[ParseResults, int, int], None, None]:
+ ) -> Generator[tuple[ParseResults, int, int], None, None]:
"""
Scan the input string for expression matches. Each match will return the
matching tokens, start location, and end location. May be called with optional
@@ -1250,7 +1267,13 @@ class ParserElement(ABC):
instring = str(instring).expandtabs()
instrlen = len(instring)
loc = 0
- preparseFn = self.preParse
+ if always_skip_whitespace:
+ preparser = Empty()
+ preparser.ignoreExprs = self.ignoreExprs
+ preparser.whiteChars = self.whiteChars
+ preparseFn = preparser.preParse
+ else:
+ preparseFn = self.preParse
parseFn = self._parse
ParserElement.resetCache()
matches = 0
@@ -1312,14 +1335,15 @@ class ParserElement(ABC):
Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York.
"""
- out: List[str] = []
+ out: list[str] = []
lastE = 0
# force preservation of s, to minimize unwanted transformation of string, and to
# keep string locs straight between transform_string and scan_string
self.keepTabs = True
try:
for t, s, e in self.scan_string(instring, debug=debug):
- out.append(instring[lastE:s])
+ if s > lastE:
+ out.append(instring[lastE:s])
lastE = e
if not t:
@@ -1373,7 +1397,12 @@ class ParserElement(ABC):
maxMatches = min(maxMatches, max_matches)
try:
return ParseResults(
- [t for t, s, e in self.scan_string(instring, maxMatches, debug=debug)]
+ [
+ t
+ for t, s, e in self.scan_string(
+ instring, maxMatches, always_skip_whitespace=False, debug=debug
+ )
+ ]
)
except ParseBaseException as exc:
if ParserElement.verbose_stacktrace:
@@ -1414,7 +1443,7 @@ class ParserElement(ABC):
last = e
yield instring[last:]
- def __add__(self, other) -> "ParserElement":
+ def __add__(self, other) -> ParserElement:
"""
Implementation of ``+`` operator - returns :class:`And`. Adding strings to a :class:`ParserElement`
converts them to :class:`Literal`\\ s by default.
@@ -1450,7 +1479,7 @@ class ParserElement(ABC):
return NotImplemented
return And([self, other])
- def __radd__(self, other) -> "ParserElement":
+ def __radd__(self, other) -> ParserElement:
"""
Implementation of ``+`` operator when left operand is not a :class:`ParserElement`
"""
@@ -1463,7 +1492,7 @@ class ParserElement(ABC):
return NotImplemented
return other + self
- def __sub__(self, other) -> "ParserElement":
+ def __sub__(self, other) -> ParserElement:
"""
Implementation of ``-`` operator, returns :class:`And` with error stop
"""
@@ -1473,7 +1502,7 @@ class ParserElement(ABC):
return NotImplemented
return self + And._ErrorStop() + other
- def __rsub__(self, other) -> "ParserElement":
+ def __rsub__(self, other) -> ParserElement:
"""
Implementation of ``-`` operator when left operand is not a :class:`ParserElement`
"""
@@ -1483,7 +1512,7 @@ class ParserElement(ABC):
return NotImplemented
return other - self
- def __mul__(self, other) -> "ParserElement":
+ def __mul__(self, other) -> ParserElement:
"""
Implementation of ``*`` operator, allows use of ``expr * 3`` in place of
``expr + expr + expr``. Expressions may also be multiplied by a 2-integer
@@ -1563,10 +1592,10 @@ class ParserElement(ABC):
ret = And([self] * minElements)
return ret
- def __rmul__(self, other) -> "ParserElement":
+ def __rmul__(self, other) -> ParserElement:
return self.__mul__(other)
- def __or__(self, other) -> "ParserElement":
+ def __or__(self, other) -> ParserElement:
"""
Implementation of ``|`` operator - returns :class:`MatchFirst`
"""
@@ -1582,7 +1611,7 @@ class ParserElement(ABC):
return NotImplemented
return MatchFirst([self, other])
- def __ror__(self, other) -> "ParserElement":
+ def __ror__(self, other) -> ParserElement:
"""
Implementation of ``|`` operator when left operand is not a :class:`ParserElement`
"""
@@ -1592,7 +1621,7 @@ class ParserElement(ABC):
return NotImplemented
return other | self
- def __xor__(self, other) -> "ParserElement":
+ def __xor__(self, other) -> ParserElement:
"""
Implementation of ``^`` operator - returns :class:`Or`
"""
@@ -1602,7 +1631,7 @@ class ParserElement(ABC):
return NotImplemented
return Or([self, other])
- def __rxor__(self, other) -> "ParserElement":
+ def __rxor__(self, other) -> ParserElement:
"""
Implementation of ``^`` operator when left operand is not a :class:`ParserElement`
"""
@@ -1612,7 +1641,7 @@ class ParserElement(ABC):
return NotImplemented
return other ^ self
- def __and__(self, other) -> "ParserElement":
+ def __and__(self, other) -> ParserElement:
"""
Implementation of ``&`` operator - returns :class:`Each`
"""
@@ -1622,7 +1651,7 @@ class ParserElement(ABC):
return NotImplemented
return Each([self, other])
- def __rand__(self, other) -> "ParserElement":
+ def __rand__(self, other) -> ParserElement:
"""
Implementation of ``&`` operator when left operand is not a :class:`ParserElement`
"""
@@ -1632,7 +1661,7 @@ class ParserElement(ABC):
return NotImplemented
return other & self
- def __invert__(self) -> "ParserElement":
+ def __invert__(self) -> ParserElement:
"""
Implementation of ``~`` operator - returns :class:`NotAny`
"""
@@ -1702,7 +1731,7 @@ class ParserElement(ABC):
return ret
- def __call__(self, name: typing.Optional[str] = None) -> "ParserElement":
+ def __call__(self, name: typing.Optional[str] = None) -> ParserElement:
"""
Shortcut for :class:`set_results_name`, with ``list_all_matches=False``.
@@ -1722,14 +1751,14 @@ class ParserElement(ABC):
return self.copy()
- def suppress(self) -> "ParserElement":
+ def suppress(self) -> ParserElement:
"""
Suppresses the output of this :class:`ParserElement`; useful to keep punctuation from
cluttering up returned output.
"""
return Suppress(self)
- def ignore_whitespace(self, recursive: bool = True) -> "ParserElement":
+ def ignore_whitespace(self, recursive: bool = True) -> ParserElement:
"""
Enables the skipping of whitespace before matching the characters in the
:class:`ParserElement`'s defined pattern.
@@ -1739,7 +1768,7 @@ class ParserElement(ABC):
self.skipWhitespace = True
return self
- def leave_whitespace(self, recursive: bool = True) -> "ParserElement":
+ def leave_whitespace(self, recursive: bool = True) -> ParserElement:
"""
Disables the skipping of whitespace before matching the characters in the
:class:`ParserElement`'s defined pattern. This is normally only used internally by
@@ -1751,8 +1780,8 @@ class ParserElement(ABC):
return self
def set_whitespace_chars(
- self, chars: Union[Set[str], str], copy_defaults: bool = False
- ) -> "ParserElement":
+ self, chars: Union[set[str], str], copy_defaults: bool = False
+ ) -> ParserElement:
"""
Overrides the default whitespace chars
"""
@@ -1761,7 +1790,7 @@ class ParserElement(ABC):
self.copyDefaultWhiteChars = copy_defaults
return self
- def parse_with_tabs(self) -> "ParserElement":
+ def parse_with_tabs(self) -> ParserElement:
"""
Overrides default behavior to expand ```` s to spaces before parsing the input string.
Must be called before ``parse_string`` when the input grammar contains elements that
@@ -1770,7 +1799,7 @@ class ParserElement(ABC):
self.keepTabs = True
return self
- def ignore(self, other: "ParserElement") -> "ParserElement":
+ def ignore(self, other: ParserElement) -> ParserElement:
"""
Define expression to be ignored (e.g., comments) while doing pattern
matching; may be called repeatedly, to define multiple comment or other
@@ -1801,7 +1830,7 @@ class ParserElement(ABC):
start_action: DebugStartAction,
success_action: DebugSuccessAction,
exception_action: DebugExceptionAction,
- ) -> "ParserElement":
+ ) -> ParserElement:
"""
Customize display of debugging messages while doing pattern matching:
@@ -1822,7 +1851,7 @@ class ParserElement(ABC):
self.debug = True
return self
- def set_debug(self, flag: bool = True, recurse: bool = False) -> "ParserElement":
+ def set_debug(self, flag: bool = True, recurse: bool = False) -> ParserElement:
"""
Enable display of debugging messages while doing pattern matching.
Set ``flag`` to ``True`` to enable, ``False`` to disable.
@@ -1887,9 +1916,14 @@ class ParserElement(ABC):
Child classes must define this method, which defines how the ``default_name`` is set.
"""
- def set_name(self, name: str) -> "ParserElement":
+ def set_name(self, name: typing.Optional[str]) -> ParserElement:
"""
- Define name for this expression, makes debugging and exception messages clearer.
+ Define name for this expression, makes debugging and exception messages clearer. If
+ `__diag__.enable_debug_on_named_expressions` is set to True, setting a name will also
+ enable debug for this expression.
+
+ If `name` is None, clears any custom name for this expression, and clears the
+ debug flag is it was enabled via `__diag__.enable_debug_on_named_expressions`.
Example::
@@ -1899,10 +1933,12 @@ class ParserElement(ABC):
integer.set_name("integer")
integer.parse_string("ABC") # -> Exception: Expected integer (at char 0), (line:1, col:1)
"""
- self.customName = name
- self.errmsg = f"Expected {self.name}"
+ self.customName = name # type: ignore[assignment]
+ self.errmsg = f"Expected {str(self)}"
+
if __diag__.enable_debug_on_named_expressions:
- self.set_debug()
+ self.set_debug(name is not None)
+
return self
@property
@@ -1910,18 +1946,22 @@ class ParserElement(ABC):
# This will use a user-defined name if available, but otherwise defaults back to the auto-generated name
return self.customName if self.customName is not None else self.default_name
+ @name.setter
+ def name(self, new_name) -> None:
+ self.set_name(new_name)
+
def __str__(self) -> str:
return self.name
def __repr__(self) -> str:
return str(self)
- def streamline(self) -> "ParserElement":
+ def streamline(self) -> ParserElement:
self.streamlined = True
self._defaultName = None
return self
- def recurse(self) -> List["ParserElement"]:
+ def recurse(self) -> list[ParserElement]:
return []
def _checkRecursion(self, parseElementList):
@@ -2008,13 +2048,15 @@ class ParserElement(ABC):
def run_tests(
self,
- tests: Union[str, List[str]],
+ tests: Union[str, list[str]],
parse_all: bool = True,
- comment: typing.Optional[Union["ParserElement", str]] = "#",
+ comment: typing.Optional[Union[ParserElement, str]] = "#",
full_dump: bool = True,
print_results: bool = True,
failure_tests: bool = False,
- post_parse: typing.Optional[Callable[[str, ParseResults], str]] = None,
+ post_parse: typing.Optional[
+ Callable[[str, ParseResults], typing.Optional[str]]
+ ] = None,
file: typing.Optional[TextIO] = None,
with_line_numbers: bool = False,
*,
@@ -2022,8 +2064,10 @@ class ParserElement(ABC):
fullDump: bool = True,
printResults: bool = True,
failureTests: bool = False,
- postParse: typing.Optional[Callable[[str, ParseResults], str]] = None,
- ) -> Tuple[bool, List[Tuple[str, Union[ParseResults, Exception]]]]:
+ postParse: typing.Optional[
+ Callable[[str, ParseResults], typing.Optional[str]]
+ ] = None,
+ ) -> tuple[bool, list[tuple[str, Union[ParseResults, Exception]]]]:
"""
Execute the parse expression on a series of test strings, showing each
test, the parsed results or where the parse failed. Quick and easy way to
@@ -2141,8 +2185,8 @@ class ParserElement(ABC):
print_ = file.write
result: Union[ParseResults, Exception]
- allResults: List[Tuple[str, Union[ParseResults, Exception]]] = []
- comments: List[str] = []
+ allResults: list[tuple[str, Union[ParseResults, Exception]]] = []
+ comments: list[str] = []
success = True
NL = Literal(r"\n").add_parse_action(replace_with("\n")).ignore(quoted_string)
BOM = "\ufeff"
@@ -2159,7 +2203,7 @@ class ParserElement(ABC):
f"{nlstr}{nlstr.join(comments) if comments else ''}",
pyparsing_test.with_line_numbers(t) if with_line_numbers else t,
]
- comments = []
+ comments.clear()
try:
# convert newline marks to actual newlines, and strip leading BOM if present
t = NL.transform_string(t.lstrip(BOM))
@@ -2173,7 +2217,18 @@ class ParserElement(ABC):
success = success and failureTests
result = pe
except Exception as exc:
- out.append(f"FAIL-EXCEPTION: {type(exc).__name__}: {exc}")
+ tag = "FAIL-EXCEPTION"
+
+ # see if this exception was raised in a parse action
+ tb = exc.__traceback__
+ it = iter(traceback.walk_tb(tb))
+ for f, line in it:
+ if (f.f_code.co_filename, line) == pa_call_line_synth:
+ next_f = next(it)[0]
+ tag += f" (raised in parse action {next_f.f_code.co_name!r})"
+ break
+
+ out.append(f"{tag}: {type(exc).__name__}: {exc}")
if ParserElement.verbose_stacktrace:
out.extend(traceback.format_tb(exc.__traceback__))
success = success and failureTests
@@ -2264,10 +2319,15 @@ class ParserElement(ABC):
# Compatibility synonyms
# fmt: off
- inlineLiteralsUsing = replaced_by_pep8("inlineLiteralsUsing", inline_literals_using)
- setDefaultWhitespaceChars = replaced_by_pep8(
+ inlineLiteralsUsing = staticmethod(replaced_by_pep8("inlineLiteralsUsing", inline_literals_using))
+ setDefaultWhitespaceChars = staticmethod(replaced_by_pep8(
"setDefaultWhitespaceChars", set_default_whitespace_chars
- )
+ ))
+ disableMemoization = staticmethod(replaced_by_pep8("disableMemoization", disable_memoization))
+ enableLeftRecursion = staticmethod(replaced_by_pep8("enableLeftRecursion", enable_left_recursion))
+ enablePackrat = staticmethod(replaced_by_pep8("enablePackrat", enable_packrat))
+ resetCache = staticmethod(replaced_by_pep8("resetCache", reset_cache))
+
setResultsName = replaced_by_pep8("setResultsName", set_results_name)
setBreak = replaced_by_pep8("setBreak", set_break)
setParseAction = replaced_by_pep8("setParseAction", set_parse_action)
@@ -2275,8 +2335,6 @@ class ParserElement(ABC):
addCondition = replaced_by_pep8("addCondition", add_condition)
setFailAction = replaced_by_pep8("setFailAction", set_fail_action)
tryParse = replaced_by_pep8("tryParse", try_parse)
- enableLeftRecursion = replaced_by_pep8("enableLeftRecursion", enable_left_recursion)
- enablePackrat = replaced_by_pep8("enablePackrat", enable_packrat)
parseString = replaced_by_pep8("parseString", parse_string)
scanString = replaced_by_pep8("scanString", scan_string)
transformString = replaced_by_pep8("transformString", transform_string)
@@ -2290,8 +2348,7 @@ class ParserElement(ABC):
setName = replaced_by_pep8("setName", set_name)
parseFile = replaced_by_pep8("parseFile", parse_file)
runTests = replaced_by_pep8("runTests", run_tests)
- canParseNext = can_parse_next
- resetCache = reset_cache
+ canParseNext = replaced_by_pep8("canParseNext", can_parse_next)
defaultName = default_name
# fmt: on
@@ -2307,7 +2364,7 @@ class _PendingSkip(ParserElement):
def _generateDefaultName(self) -> str:
return str(self.anchor + Empty()).replace("Empty", "...")
- def __add__(self, other) -> "ParserElement":
+ def __add__(self, other) -> ParserElement:
skipper = SkipTo(other).set_name("...")("_skipped*")
if self.must_skip:
@@ -2331,7 +2388,7 @@ class _PendingSkip(ParserElement):
def __repr__(self):
return self.defaultName
- def parseImpl(self, *args):
+ def parseImpl(self, *args) -> ParseImplReturnType:
raise Exception(
"use of `...` expression without following SkipTo target expression"
)
@@ -2360,7 +2417,7 @@ class NoMatch(Token):
self.mayIndexError = False
self.errmsg = "Unmatchable token"
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
raise ParseException(instring, loc, self.errmsg, self)
@@ -2409,7 +2466,7 @@ class Literal(Token):
def _generateDefaultName(self) -> str:
return repr(self.match)
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
if instring[loc] == self.firstMatchChar and instring.startswith(
self.match, loc
):
@@ -2430,12 +2487,12 @@ class Empty(Literal):
def _generateDefaultName(self) -> str:
return "Empty"
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
return loc, []
class _SingleCharLiteral(Literal):
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
if instring[loc] == self.firstMatchChar:
return loc + 1, self.match
raise ParseException(instring, loc, self.errmsg, self)
@@ -2489,9 +2546,8 @@ class Keyword(Token):
match_string = matchString or match_string
self.match = match_string
self.matchLen = len(match_string)
- try:
- self.firstMatchChar = match_string[0]
- except IndexError:
+ self.firstMatchChar = match_string[:1]
+ if not self.firstMatchChar:
raise ValueError("null string passed to Keyword; use Empty() instead")
self.errmsg = f"Expected {type(self).__name__} {self.name}"
self.mayReturnEmpty = False
@@ -2505,8 +2561,8 @@ class Keyword(Token):
def _generateDefaultName(self) -> str:
return repr(self.match)
- def parseImpl(self, instring, loc, doActions=True):
- errmsg = self.errmsg
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
+ errmsg = self.errmsg or ""
errloc = loc
if self.caseless:
if instring[loc : loc + self.matchLen].upper() == self.caselessmatch:
@@ -2556,7 +2612,10 @@ class Keyword(Token):
"""
Keyword.DEFAULT_KEYWORD_CHARS = chars
- setDefaultKeywordChars = set_default_keyword_chars
+ # Compatibility synonyms
+ setDefaultKeywordChars = staticmethod(
+ replaced_by_pep8("setDefaultKeywordChars", set_default_keyword_chars)
+ )
class CaselessLiteral(Literal):
@@ -2580,7 +2639,7 @@ class CaselessLiteral(Literal):
self.returnString = match_string
self.errmsg = f"Expected {self.name}"
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
if instring[loc : loc + self.matchLen].upper() == self.match:
return loc + self.matchLen, self.returnString
raise ParseException(instring, loc, self.errmsg, self)
@@ -2666,7 +2725,7 @@ class CloseMatch(Token):
def _generateDefaultName(self) -> str:
return f"{type(self).__name__}:{self.match_string!r}"
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
start = loc
instrlen = len(instring)
maxloc = start + len(self.match_string)
@@ -2881,7 +2940,7 @@ class Word(Token):
self.re = None # type: ignore[assignment]
else:
self.re_match = self.re.match
- self.parseImpl = self.parseImpl_regex # type: ignore[assignment]
+ self.parseImpl = self.parseImpl_regex # type: ignore[method-assign]
def _generateDefaultName(self) -> str:
def charsAsStr(s):
@@ -2911,36 +2970,36 @@ class Word(Token):
return base + f"{{{self.minLen},{self.maxLen}}}"
return base
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
if instring[loc] not in self.initChars:
raise ParseException(instring, loc, self.errmsg, self)
start = loc
loc += 1
instrlen = len(instring)
- bodychars = self.bodyChars
+ body_chars: set[str] = self.bodyChars
maxloc = start + self.maxLen
maxloc = min(maxloc, instrlen)
- while loc < maxloc and instring[loc] in bodychars:
+ while loc < maxloc and instring[loc] in body_chars:
loc += 1
- throwException = False
+ throw_exception = False
if loc - start < self.minLen:
- throwException = True
- elif self.maxSpecified and loc < instrlen and instring[loc] in bodychars:
- throwException = True
+ throw_exception = True
+ elif self.maxSpecified and loc < instrlen and instring[loc] in body_chars:
+ throw_exception = True
elif self.asKeyword and (
- (start > 0 and instring[start - 1] in bodychars)
- or (loc < instrlen and instring[loc] in bodychars)
+ (start > 0 and instring[start - 1] in body_chars)
+ or (loc < instrlen and instring[loc] in body_chars)
):
- throwException = True
+ throw_exception = True
- if throwException:
+ if throw_exception:
raise ParseException(instring, loc, self.errmsg, self)
return loc, instring[start:loc]
- def parseImpl_regex(self, instring, loc, doActions=True):
+ def parseImpl_regex(self, instring, loc, do_actions=True) -> ParseImplReturnType:
result = self.re_match(instring, loc)
if not result:
raise ParseException(instring, loc, self.errmsg, self)
@@ -3021,49 +3080,67 @@ class Regex(Token):
self._re = None
self.reString = self.pattern = pattern
- self.flags = flags
elif hasattr(pattern, "pattern") and hasattr(pattern, "match"):
self._re = pattern
self.pattern = self.reString = pattern.pattern
- self.flags = flags
+
+ elif callable(pattern):
+ # defer creating this pattern until we really need it
+ self.pattern = pattern
+ self._re = None
else:
raise TypeError(
- "Regex may only be constructed with a string or a compiled RE object"
+ "Regex may only be constructed with a string or a compiled RE object,"
+ " or a callable that takes no arguments and returns a string or a"
+ " compiled RE object"
)
+ self.flags = flags
self.errmsg = f"Expected {self.name}"
self.mayIndexError = False
self.asGroupList = asGroupList
self.asMatch = asMatch
if self.asGroupList:
- self.parseImpl = self.parseImplAsGroupList # type: ignore [assignment]
+ self.parseImpl = self.parseImplAsGroupList # type: ignore [method-assign]
if self.asMatch:
- self.parseImpl = self.parseImplAsMatch # type: ignore [assignment]
+ self.parseImpl = self.parseImplAsMatch # type: ignore [method-assign]
@cached_property
- def re(self):
+ def re(self) -> re.Pattern:
if self._re:
return self._re
+ if callable(self.pattern):
+ # replace self.pattern with the string returned by calling self.pattern()
+ self.pattern = cast(Callable[[], str], self.pattern)()
+
+ # see if we got a compiled RE back instead of a str - if so, we're done
+ if hasattr(self.pattern, "pattern") and hasattr(self.pattern, "match"):
+ self._re = cast(re.Pattern[str], self.pattern)
+ self.pattern = self.reString = self._re.pattern
+ return self._re
+
try:
- return re.compile(self.pattern, self.flags)
+ self._re = re.compile(self.pattern, self.flags)
+ return self._re
except re.error:
raise ValueError(f"invalid pattern ({self.pattern!r}) passed to Regex")
@cached_property
- def re_match(self):
+ def re_match(self) -> Callable[[str, int], Any]:
return self.re.match
@cached_property
- def mayReturnEmpty(self):
- return self.re_match("") is not None
+ def mayReturnEmpty(self) -> bool: # type: ignore[override]
+ return self.re_match("", 0) is not None
def _generateDefaultName(self) -> str:
- return "Re:({})".format(repr(self.pattern).replace("\\\\", "\\"))
+ unescaped = repr(self.pattern).replace("\\\\", "\\")
+ return f"Re:({unescaped})"
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
result = self.re_match(instring, loc)
if not result:
raise ParseException(instring, loc, self.errmsg, self)
@@ -3077,7 +3154,7 @@ class Regex(Token):
return loc, ret
- def parseImplAsGroupList(self, instring, loc, doActions=True):
+ def parseImplAsGroupList(self, instring, loc, do_actions=True):
result = self.re_match(instring, loc)
if not result:
raise ParseException(instring, loc, self.errmsg, self)
@@ -3086,7 +3163,7 @@ class Regex(Token):
ret = result.groups()
return loc, ret
- def parseImplAsMatch(self, instring, loc, doActions=True):
+ def parseImplAsMatch(self, instring, loc, do_actions=True):
result = self.re_match(instring, loc)
if not result:
raise ParseException(instring, loc, self.errmsg, self)
@@ -3223,7 +3300,7 @@ class QuotedString(Token):
# fmt: off
# build up re pattern for the content between the quote delimiters
- inner_pattern = []
+ inner_pattern: list[str] = []
if esc_quote:
inner_pattern.append(rf"(?:{re.escape(esc_quote)})")
@@ -3245,12 +3322,12 @@ class QuotedString(Token):
self.re_flags |= re.MULTILINE | re.DOTALL
inner_pattern.append(
rf"(?:[^{_escape_regex_range_chars(self.end_quote_char[0])}"
- rf"{(_escape_regex_range_chars(esc_char) if self.has_esc_char else '')}])"
+ rf"{(_escape_regex_range_chars(self.esc_char) if self.has_esc_char else '')}])"
)
else:
inner_pattern.append(
rf"(?:[^{_escape_regex_range_chars(self.end_quote_char[0])}\n\r"
- rf"{(_escape_regex_range_chars(esc_char) if self.has_esc_char else '')}])"
+ rf"{(_escape_regex_range_chars(self.esc_char) if self.has_esc_char else '')}])"
)
self.pattern = "".join(
@@ -3267,6 +3344,7 @@ class QuotedString(Token):
if self.convert_whitespace_escapes:
self.unquote_scan_re = re.compile(
rf"({'|'.join(re.escape(k) for k in self.ws_map)})"
+ rf"|(\\[0-7]{3}|\\0|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4})"
rf"|({re.escape(self.esc_char)}.)"
rf"|(\n|.)",
flags=self.re_flags,
@@ -3298,7 +3376,7 @@ class QuotedString(Token):
return f"quoted string, starting with {self.quote_char} ending with {self.end_quote_char}"
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
# check first character of opening quote to see if that is a match
# before doing the more complicated regex match
result = (
@@ -3313,6 +3391,16 @@ class QuotedString(Token):
loc = result.end()
ret = result.group()
+ def convert_escaped_numerics(s: str) -> str:
+ if s == "0":
+ return "\0"
+ if s.isdigit() and len(s) == 3:
+ return chr(int(s, base=8))
+ elif s.startswith(("u", "x")):
+ return chr(int(s[1:], base=16))
+ else:
+ return s
+
if self.unquote_results:
# strip off quotes
ret = ret[self.quote_char_len : -self.end_quote_char_len]
@@ -3326,10 +3414,13 @@ class QuotedString(Token):
ret = "".join(
# match group 1 matches \t, \n, etc.
self.ws_map[match.group(1)] if match.group(1)
- # match group 2 matches escaped characters
- else match.group(2)[-1] if match.group(2)
- # match group 3 matches any character
- else match.group(3)
+ # match group 2 matches escaped octal, null, hex, and Unicode
+ # sequences
+ else convert_escaped_numerics(match.group(2)[1:]) if match.group(2)
+ # match group 3 matches escaped characters
+ else match.group(3)[-1] if match.group(3)
+ # match group 4 matches any character
+ else match.group(4)
for match in self.unquote_scan_re.finditer(ret)
)
else:
@@ -3412,7 +3503,7 @@ class CharsNotIn(Token):
else:
return f"!W:({self.notChars})"
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
notchars = self.notCharsSet
if instring[loc] in notchars:
raise ParseException(instring, loc, self.errmsg, self)
@@ -3490,7 +3581,7 @@ class White(Token):
def _generateDefaultName(self) -> str:
return "".join(White.whiteStrs[c] for c in self.matchWhite)
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
if instring[loc] not in self.matchWhite:
raise ParseException(instring, loc, self.errmsg, self)
start = loc
@@ -3538,7 +3629,7 @@ class GoToColumn(PositionToken):
return loc
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
thiscol = col(loc, instring)
if thiscol > self.col:
raise ParseException(instring, loc, "Text not in expected column", self)
@@ -3576,7 +3667,7 @@ class LineStart(PositionToken):
self.orig_whiteChars = set() | self.whiteChars
self.whiteChars.discard("\n")
self.skipper = Empty().set_whitespace_chars(self.whiteChars)
- self.errmsg = "Expected start of line"
+ self.set_name("start of line")
def preParse(self, instring: str, loc: int) -> int:
if loc == 0:
@@ -3590,7 +3681,7 @@ class LineStart(PositionToken):
return ret
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
if col(loc, instring) == 1:
return loc, []
raise ParseException(instring, loc, self.errmsg, self)
@@ -3605,9 +3696,9 @@ class LineEnd(PositionToken):
super().__init__()
self.whiteChars.discard("\n")
self.set_whitespace_chars(self.whiteChars, copy_defaults=False)
- self.errmsg = "Expected end of line"
+ self.set_name("end of line")
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
if loc < len(instring):
if instring[loc] == "\n":
return loc + 1, "\n"
@@ -3626,9 +3717,9 @@ class StringStart(PositionToken):
def __init__(self):
super().__init__()
- self.errmsg = "Expected start of text"
+ self.set_name("start of text")
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
# see if entire string up to here is just whitespace and ignoreables
if loc != 0 and loc != self.preParse(instring, 0):
raise ParseException(instring, loc, self.errmsg, self)
@@ -3643,9 +3734,9 @@ class StringEnd(PositionToken):
def __init__(self):
super().__init__()
- self.errmsg = "Expected end of text"
+ self.set_name("end of text")
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
if loc < len(instring):
raise ParseException(instring, loc, self.errmsg, self)
if loc == len(instring):
@@ -3670,9 +3761,9 @@ class WordStart(PositionToken):
wordChars = word_chars if wordChars == printables else wordChars
super().__init__()
self.wordChars = set(wordChars)
- self.errmsg = "Not at the start of a word"
+ self.set_name("start of a word")
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
if loc != 0:
if (
instring[loc - 1] in self.wordChars
@@ -3696,9 +3787,9 @@ class WordEnd(PositionToken):
super().__init__()
self.wordChars = set(wordChars)
self.skipWhitespace = False
- self.errmsg = "Not at the end of a word"
+ self.set_name("end of a word")
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
instrlen = len(instring)
if instrlen > 0 and loc < instrlen:
if (
@@ -3709,6 +3800,48 @@ class WordEnd(PositionToken):
return loc, []
+class Tag(Token):
+ """
+ A meta-element for inserting a named result into the parsed
+ tokens that may be checked later in a parse action or while
+ processing the parsed results. Accepts an optional tag value,
+ defaulting to `True`.
+
+ Example::
+
+ end_punc = "." | ("!" + Tag("enthusiastic")))
+ greeting = "Hello," + Word(alphas) + end_punc
+
+ result = greeting.parse_string("Hello, World.")
+ print(result.dump())
+
+ result = greeting.parse_string("Hello, World!")
+ print(result.dump())
+
+ prints::
+
+ ['Hello,', 'World', '.']
+
+ ['Hello,', 'World', '!']
+ - enthusiastic: True
+ """
+
+ def __init__(self, tag_name: str, value: Any = True):
+ super().__init__()
+ self.mayReturnEmpty = True
+ self.mayIndexError = False
+ self.leave_whitespace()
+ self.tag_name = tag_name
+ self.tag_value = value
+ self.add_parse_action(self._add_tag)
+
+ def _add_tag(self, tokens: ParseResults):
+ tokens[self.tag_name] = self.tag_value
+
+ def _generateDefaultName(self) -> str:
+ return f"{type(self).__name__}:{self.tag_name}={self.tag_value!r}"
+
+
class ParseExpression(ParserElement):
"""Abstract subclass of ParserElement, for combining and
post-processing parsed tokens.
@@ -3716,7 +3849,7 @@ class ParseExpression(ParserElement):
def __init__(self, exprs: typing.Iterable[ParserElement], savelist: bool = False):
super().__init__(savelist)
- self.exprs: List[ParserElement]
+ self.exprs: list[ParserElement]
if isinstance(exprs, _generatorType):
exprs = list(exprs)
@@ -3740,7 +3873,7 @@ class ParseExpression(ParserElement):
self.exprs = [exprs]
self.callPreparse = False
- def recurse(self) -> List[ParserElement]:
+ def recurse(self) -> list[ParserElement]:
return self.exprs[:]
def append(self, other) -> ParserElement:
@@ -3846,13 +3979,13 @@ class ParseExpression(ParserElement):
ret.exprs = [e.copy() for e in self.exprs]
return ret
- def _setResultsName(self, name, listAllMatches=False):
+ def _setResultsName(self, name, list_all_matches=False) -> ParserElement:
if not (
__diag__.warn_ungrouped_named_tokens_in_collection
and Diagnostics.warn_ungrouped_named_tokens_in_collection
not in self.suppress_warnings_
):
- return super()._setResultsName(name, listAllMatches)
+ return super()._setResultsName(name, list_all_matches)
for e in self.exprs:
if (
@@ -3871,7 +4004,7 @@ class ParseExpression(ParserElement):
warnings.warn(warning, stacklevel=3)
break
- return super()._setResultsName(name, listAllMatches)
+ return super()._setResultsName(name, list_all_matches)
# Compatibility synonyms
# fmt: off
@@ -3882,7 +4015,7 @@ class ParseExpression(ParserElement):
class And(ParseExpression):
"""
- Requires all given :class:`ParseExpression` s to be found in the given order.
+ Requires all given :class:`ParserElement` s to be found in the given order.
Expressions may be separated by whitespace.
May be constructed using the ``'+'`` operator.
May also be constructed using the ``'-'`` operator, which will
@@ -3909,9 +4042,9 @@ class And(ParseExpression):
def __init__(
self, exprs_arg: typing.Iterable[ParserElement], savelist: bool = True
):
- exprs: List[ParserElement] = list(exprs_arg)
+ exprs: list[ParserElement] = list(exprs_arg)
if exprs and Ellipsis in exprs:
- tmp = []
+ tmp: list[ParserElement] = []
for i, expr in enumerate(exprs):
if expr is not Ellipsis:
tmp.append(expr)
@@ -3991,11 +4124,11 @@ class And(ParseExpression):
self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs)
return self
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True):
# pass False as callPreParse arg to _parse for first element, since we already
# pre-parsed the string as part of our And pre-parsing
loc, resultlist = self.exprs[0]._parse(
- instring, loc, doActions, callPreParse=False
+ instring, loc, do_actions, callPreParse=False
)
errorStop = False
for e in self.exprs[1:]:
@@ -4005,7 +4138,7 @@ class And(ParseExpression):
continue
if errorStop:
try:
- loc, exprtokens = e._parse(instring, loc, doActions)
+ loc, exprtokens = e._parse(instring, loc, do_actions)
except ParseSyntaxException:
raise
except ParseBaseException as pe:
@@ -4016,7 +4149,7 @@ class And(ParseExpression):
instring, len(instring), self.errmsg, self
)
else:
- loc, exprtokens = e._parse(instring, loc, doActions)
+ loc, exprtokens = e._parse(instring, loc, do_actions)
resultlist += exprtokens
return loc, resultlist
@@ -4043,7 +4176,7 @@ class And(ParseExpression):
class Or(ParseExpression):
- """Requires that at least one :class:`ParseExpression` is found. If
+ """Requires that at least one :class:`ParserElement` is found. If
two expressions match, the expression that matches the longest
string will be used. May be constructed using the ``'^'``
operator.
@@ -4080,11 +4213,11 @@ class Or(ParseExpression):
self.saveAsList = False
return self
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
maxExcLoc = -1
maxException = None
- matches = []
- fatals = []
+ matches: list[tuple[int, ParserElement]] = []
+ fatals: list[ParseFatalException] = []
if all(e.callPreparse for e in self.exprs):
loc = self.preParse(instring, loc)
for e in self.exprs:
@@ -4117,20 +4250,20 @@ class Or(ParseExpression):
# might change whether or how much they match of the input.
matches.sort(key=itemgetter(0), reverse=True)
- if not doActions:
+ if not do_actions:
# no further conditions or parse actions to change the selection of
# alternative, so the first match will be the best match
best_expr = matches[0][1]
- return best_expr._parse(instring, loc, doActions)
+ return best_expr._parse(instring, loc, do_actions)
- longest = -1, None
+ longest: tuple[int, typing.Optional[ParseResults]] = -1, None
for loc1, expr1 in matches:
if loc1 <= longest[0]:
# already have a longer match than this one will deliver, we are done
return longest
try:
- loc2, toks = expr1._parse(instring, loc, doActions)
+ loc2, toks = expr1._parse(instring, loc, do_actions)
except ParseException as err:
err.__traceback__ = None
if err.loc > maxExcLoc:
@@ -4158,7 +4291,7 @@ class Or(ParseExpression):
# infer from this check that all alternatives failed at the current position
# so emit this collective error message instead of any single error message
if maxExcLoc == loc:
- maxException.msg = self.errmsg
+ maxException.msg = self.errmsg or ""
raise maxException
raise ParseException(instring, loc, "no defined alternatives to match", self)
@@ -4173,7 +4306,7 @@ class Or(ParseExpression):
def _generateDefaultName(self) -> str:
return f"{{{' ^ '.join(str(e) for e in self.exprs)}}}"
- def _setResultsName(self, name, listAllMatches=False):
+ def _setResultsName(self, name, list_all_matches=False) -> ParserElement:
if (
__diag__.warn_multiple_tokens_in_named_alternation
and Diagnostics.warn_multiple_tokens_in_named_alternation
@@ -4194,11 +4327,11 @@ class Or(ParseExpression):
)
warnings.warn(warning, stacklevel=3)
- return super()._setResultsName(name, listAllMatches)
+ return super()._setResultsName(name, list_all_matches)
class MatchFirst(ParseExpression):
- """Requires that at least one :class:`ParseExpression` is found. If
+ """Requires that at least one :class:`ParserElement` is found. If
more than one expression matches, the first one listed is the one that will
match. May be constructed using the ``'|'`` operator.
@@ -4239,13 +4372,13 @@ class MatchFirst(ParseExpression):
self.mayReturnEmpty = True
return self
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
maxExcLoc = -1
maxException = None
for e in self.exprs:
try:
- return e._parse(instring, loc, doActions)
+ return e._parse(instring, loc, do_actions)
except ParseFatalException as pfe:
pfe.__traceback__ = None
pfe.parser_element = e
@@ -4265,7 +4398,7 @@ class MatchFirst(ParseExpression):
# infer from this check that all alternatives failed at the current position
# so emit this collective error message instead of any individual error message
if maxExcLoc == loc:
- maxException.msg = self.errmsg
+ maxException.msg = self.errmsg or ""
raise maxException
raise ParseException(instring, loc, "no defined alternatives to match", self)
@@ -4280,7 +4413,7 @@ class MatchFirst(ParseExpression):
def _generateDefaultName(self) -> str:
return f"{{{' | '.join(str(e) for e in self.exprs)}}}"
- def _setResultsName(self, name, listAllMatches=False):
+ def _setResultsName(self, name, list_all_matches=False) -> ParserElement:
if (
__diag__.warn_multiple_tokens_in_named_alternation
and Diagnostics.warn_multiple_tokens_in_named_alternation
@@ -4301,11 +4434,11 @@ class MatchFirst(ParseExpression):
)
warnings.warn(warning, stacklevel=3)
- return super()._setResultsName(name, listAllMatches)
+ return super()._setResultsName(name, list_all_matches)
class Each(ParseExpression):
- """Requires all given :class:`ParseExpression` s to be found, but in
+ """Requires all given :class:`ParserElement` s to be found, but in
any order. Expressions may be separated by whitespace.
May be constructed using the ``'&'`` operator.
@@ -4387,7 +4520,7 @@ class Each(ParseExpression):
self.mayReturnEmpty = True
return self
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
if self.initExprGroups:
self.opt1map = dict(
(id(e.expr), e) for e in self.exprs if isinstance(e, Opt)
@@ -4419,11 +4552,11 @@ class Each(ParseExpression):
tmpReqd = self.required[:]
tmpOpt = self.optionals[:]
multis = self.multioptionals[:]
- matchOrder = []
+ matchOrder: list[ParserElement] = []
keepMatching = True
- failed = []
- fatals = []
+ failed: list[ParserElement] = []
+ fatals: list[ParseFatalException] = []
while keepMatching:
tmpExprs = tmpReqd + tmpOpt + multis
failed.clear()
@@ -4469,7 +4602,7 @@ class Each(ParseExpression):
total_results = ParseResults([])
for e in matchOrder:
- loc, results = e._parse(instring, loc, doActions)
+ loc, results = e._parse(instring, loc, do_actions)
total_results += results
return loc, total_results
@@ -4506,17 +4639,22 @@ class ParseElementEnhance(ParserElement):
self.callPreparse = expr.callPreparse
self.ignoreExprs.extend(expr.ignoreExprs)
- def recurse(self) -> List[ParserElement]:
+ def recurse(self) -> list[ParserElement]:
return [self.expr] if self.expr is not None else []
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True):
if self.expr is None:
raise ParseException(instring, loc, "No expression defined", self)
try:
- return self.expr._parse(instring, loc, doActions, callPreParse=False)
+ return self.expr._parse(instring, loc, do_actions, callPreParse=False)
+ except ParseSyntaxException:
+ raise
except ParseBaseException as pbe:
- if not isinstance(self, Forward) or self.customName is not None:
+ pbe.pstr = pbe.pstr or instring
+ pbe.loc = pbe.loc or loc
+ pbe.parser_element = pbe.parser_element or self
+ if not isinstance(self, Forward) and self.customName is not None:
if self.errmsg:
pbe.msg = self.errmsg
raise
@@ -4611,14 +4749,14 @@ class IndentedBlock(ParseElementEnhance):
self._grouped = grouped
self.parent_anchor = 1
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
# advance parse position to non-whitespace by using an Empty()
# this should be the column to be used for all subsequent indented lines
anchor_loc = Empty().preParse(instring, loc)
# see if self.expr matches at the current location - if not it will raise an exception
# and no further work is necessary
- self.expr.try_parse(instring, anchor_loc, do_actions=doActions)
+ self.expr.try_parse(instring, anchor_loc, do_actions=do_actions)
indent_col = col(anchor_loc, instring)
peer_detect_expr = self._Indent(indent_col)
@@ -4641,9 +4779,9 @@ class IndentedBlock(ParseElementEnhance):
if self._grouped:
wrapper = Group
else:
- wrapper = lambda expr: expr
+ wrapper = lambda expr: expr # type: ignore[misc, assignment]
return (wrapper(block) + Optional(trailing_undent)).parseImpl(
- instring, anchor_loc, doActions
+ instring, anchor_loc, do_actions
)
@@ -4662,10 +4800,10 @@ class AtStringStart(ParseElementEnhance):
super().__init__(expr)
self.callPreparse = False
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
if loc != 0:
raise ParseException(instring, loc, "not found at string start")
- return super().parseImpl(instring, loc, doActions)
+ return super().parseImpl(instring, loc, do_actions)
class AtLineStart(ParseElementEnhance):
@@ -4695,10 +4833,10 @@ class AtLineStart(ParseElementEnhance):
super().__init__(expr)
self.callPreparse = False
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
if col(loc, instring) != 1:
raise ParseException(instring, loc, "not found at line start")
- return super().parseImpl(instring, loc, doActions)
+ return super().parseImpl(instring, loc, do_actions)
class FollowedBy(ParseElementEnhance):
@@ -4728,10 +4866,10 @@ class FollowedBy(ParseElementEnhance):
super().__init__(expr)
self.mayReturnEmpty = True
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
# by using self._expr.parse and deleting the contents of the returned ParseResults list
# we keep any named results that were defined in the FollowedBy expression
- _, ret = self.expr._parse(instring, loc, doActions=doActions)
+ _, ret = self.expr._parse(instring, loc, do_actions=do_actions)
del ret[:]
return loc, ret
@@ -4767,9 +4905,7 @@ class PrecededBy(ParseElementEnhance):
"""
- def __init__(
- self, expr: Union[ParserElement, str], retreat: typing.Optional[int] = None
- ):
+ def __init__(self, expr: Union[ParserElement, str], retreat: int = 0):
super().__init__(expr)
self.expr = self.expr().leave_whitespace()
self.mayReturnEmpty = True
@@ -4793,10 +4929,10 @@ class PrecededBy(ParseElementEnhance):
self.skipWhitespace = False
self.parseAction.append(lambda s, l, t: t.__delitem__(slice(None, None)))
- def parseImpl(self, instring, loc=0, doActions=True):
+ def parseImpl(self, instring, loc=0, do_actions=True) -> ParseImplReturnType:
if self.exact:
if loc < self.retreat:
- raise ParseException(instring, loc, self.errmsg)
+ raise ParseException(instring, loc, self.errmsg, self)
start = loc - self.retreat
_, ret = self.expr._parse(instring, start)
return loc, ret
@@ -4804,7 +4940,7 @@ class PrecededBy(ParseElementEnhance):
# retreat specified a maximum lookbehind window, iterate
test_expr = self.expr + StringEnd()
instring_slice = instring[max(0, loc - self.retreat) : loc]
- last_expr = ParseException(instring, loc, self.errmsg)
+ last_expr: ParseBaseException = ParseException(instring, loc, self.errmsg, self)
for offset in range(1, min(loc, self.retreat + 1) + 1):
try:
@@ -4848,9 +4984,9 @@ class Located(ParseElementEnhance):
"""
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
start = loc
- loc, tokens = self.expr._parse(instring, start, doActions, callPreParse=False)
+ loc, tokens = self.expr._parse(instring, start, do_actions, callPreParse=False)
ret_tokens = ParseResults([start, tokens, loc])
ret_tokens["locn_start"] = start
ret_tokens["value"] = tokens
@@ -4896,8 +5032,8 @@ class NotAny(ParseElementEnhance):
self.mayReturnEmpty = True
self.errmsg = f"Found unwanted token, {self.expr}"
- def parseImpl(self, instring, loc, doActions=True):
- if self.expr.can_parse_next(instring, loc, do_actions=doActions):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
+ if self.expr.can_parse_next(instring, loc, do_actions=do_actions):
raise ParseException(instring, loc, self.errmsg, self)
return loc, []
@@ -4927,7 +5063,7 @@ class _MultipleMatch(ParseElementEnhance):
self.not_ender = ~ender if ender is not None else None
return self
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
self_expr_parse = self.expr._parse
self_skip_ignorables = self._skipIgnorables
check_ender = self.not_ender is not None
@@ -4938,7 +5074,7 @@ class _MultipleMatch(ParseElementEnhance):
# if so, fail)
if check_ender:
try_not_ender(instring, loc)
- loc, tokens = self_expr_parse(instring, loc, doActions)
+ loc, tokens = self_expr_parse(instring, loc, do_actions)
try:
hasIgnoreExprs = not not self.ignoreExprs
while 1:
@@ -4948,14 +5084,14 @@ class _MultipleMatch(ParseElementEnhance):
preloc = self_skip_ignorables(instring, loc)
else:
preloc = loc
- loc, tmptokens = self_expr_parse(instring, preloc, doActions)
+ loc, tmptokens = self_expr_parse(instring, preloc, do_actions)
tokens += tmptokens
except (ParseException, IndexError):
pass
return loc, tokens
- def _setResultsName(self, name, listAllMatches=False):
+ def _setResultsName(self, name, list_all_matches=False) -> ParserElement:
if (
__diag__.warn_ungrouped_named_tokens_in_collection
and Diagnostics.warn_ungrouped_named_tokens_in_collection
@@ -4978,7 +5114,7 @@ class _MultipleMatch(ParseElementEnhance):
warnings.warn(warning, stacklevel=3)
break
- return super()._setResultsName(name, listAllMatches)
+ return super()._setResultsName(name, list_all_matches)
class OneOrMore(_MultipleMatch):
@@ -5037,9 +5173,9 @@ class ZeroOrMore(_MultipleMatch):
super().__init__(expr, stopOn=stopOn or stop_on)
self.mayReturnEmpty = True
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
try:
- return super().parseImpl(instring, loc, doActions)
+ return super().parseImpl(instring, loc, do_actions)
except (ParseException, IndexError):
return loc, ParseResults([], name=self.resultsName)
@@ -5170,10 +5306,12 @@ class Opt(ParseElementEnhance):
self.defaultValue = default
self.mayReturnEmpty = True
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
self_expr = self.expr
try:
- loc, tokens = self_expr._parse(instring, loc, doActions, callPreParse=False)
+ loc, tokens = self_expr._parse(
+ instring, loc, do_actions, callPreParse=False
+ )
except (ParseException, IndexError):
default_value = self.defaultValue
if default_value is not self.__optionalNotMatched:
@@ -5181,9 +5319,9 @@ class Opt(ParseElementEnhance):
tokens = ParseResults([default_value])
tokens[self_expr.resultsName] = default_value
else:
- tokens = [default_value]
+ tokens = [default_value] # type: ignore[assignment]
else:
- tokens = []
+ tokens = [] # type: ignore[assignment]
return loc, tokens
def _generateDefaultName(self) -> str:
@@ -5279,7 +5417,7 @@ class SkipTo(ParseElementEnhance):
self.failOn = self._literalStringClass(failOn)
else:
self.failOn = failOn
- self.errmsg = "No match found for " + str(self.expr)
+ self.errmsg = f"No match found for {self.expr}"
self.ignorer = Empty().leave_whitespace()
self._update_ignorer()
@@ -5295,7 +5433,7 @@ class SkipTo(ParseElementEnhance):
super().ignore(expr)
self._update_ignorer()
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True):
startloc = loc
instrlen = len(instring)
self_expr_parse = self.expr._parse
@@ -5325,7 +5463,7 @@ class SkipTo(ParseElementEnhance):
prev_tmploc = tmploc
try:
- self_expr_parse(instring, tmploc, doActions=False, callPreParse=False)
+ self_expr_parse(instring, tmploc, do_actions=False, callPreParse=False)
except (ParseException, IndexError):
# no match, advance loc in string
tmploc += 1
@@ -5343,7 +5481,7 @@ class SkipTo(ParseElementEnhance):
skipresult = ParseResults(skiptext)
if self.includeMatch:
- loc, mat = self_expr_parse(instring, loc, doActions, callPreParse=False)
+ loc, mat = self_expr_parse(instring, loc, do_actions, callPreParse=False)
skipresult += mat
return loc, skipresult
@@ -5383,7 +5521,7 @@ class Forward(ParseElementEnhance):
super().__init__(other, savelist=False) # type: ignore[arg-type]
self.lshift_line = None
- def __lshift__(self, other) -> "Forward":
+ def __lshift__(self, other) -> Forward:
if hasattr(self, "caller_frame"):
del self.caller_frame
if isinstance(other, str_type):
@@ -5405,13 +5543,13 @@ class Forward(ParseElementEnhance):
self.lshift_line = traceback.extract_stack(limit=2)[-2] # type: ignore[assignment]
return self
- def __ilshift__(self, other) -> "Forward":
+ def __ilshift__(self, other) -> Forward:
if not isinstance(other, ParserElement):
return NotImplemented
return self << other
- def __or__(self, other) -> "ParserElement":
+ def __or__(self, other) -> ParserElement:
caller_line = traceback.extract_stack(limit=2)[-2]
if (
__diag__.warn_on_match_first_with_lshift_operator
@@ -5440,7 +5578,7 @@ class Forward(ParseElementEnhance):
lineno=self.caller_frame.lineno,
)
- def parseImpl(self, instring, loc, doActions=True):
+ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType:
if (
self.expr is None
and __diag__.warn_on_parse_using_empty_Forward
@@ -5466,7 +5604,7 @@ class Forward(ParseElementEnhance):
stacklevel=stacklevel,
)
if not ParserElement._left_recursion_enabled:
- return super().parseImpl(instring, loc, doActions)
+ return super().parseImpl(instring, loc, do_actions)
# ## Bounded Recursion algorithm ##
# Recursion only needs to be processed at ``Forward`` elements, since they are
# the only ones that can actually refer to themselves. The general idea is
@@ -5484,13 +5622,13 @@ class Forward(ParseElementEnhance):
#
# There is a complication since we not only *parse* but also *transform* via
# actions: We do not want to run the actions too often while expanding. Thus,
- # we expand using `doActions=False` and only run `doActions=True` if the next
+ # we expand using `do_actions=False` and only run `do_actions=True` if the next
# recursion level is acceptable.
with ParserElement.recursion_lock:
memo = ParserElement.recursion_memos
try:
# we are parsing at a specific recursion expansion - use it as-is
- prev_loc, prev_result = memo[loc, self, doActions]
+ prev_loc, prev_result = memo[loc, self, do_actions]
if isinstance(prev_result, Exception):
raise prev_result
return prev_loc, prev_result.copy()
@@ -5498,14 +5636,14 @@ class Forward(ParseElementEnhance):
act_key = (loc, self, True)
peek_key = (loc, self, False)
# we are searching for the best recursion expansion - keep on improving
- # both `doActions` cases must be tracked separately here!
+ # both `do_actions` cases must be tracked separately here!
prev_loc, prev_peek = memo[peek_key] = (
loc - 1,
ParseException(
instring, loc, "Forward recursion without base case", self
),
)
- if doActions:
+ if do_actions:
memo[act_key] = memo[peek_key]
while True:
try:
@@ -5517,16 +5655,16 @@ class Forward(ParseElementEnhance):
new_loc, new_peek = prev_loc, prev_peek
# the match did not get better: we are done
if new_loc <= prev_loc:
- if doActions:
- # replace the match for doActions=False as well,
+ if do_actions:
+ # replace the match for do_actions=False as well,
# in case the action did backtrack
prev_loc, prev_result = memo[peek_key] = memo[act_key]
del memo[peek_key], memo[act_key]
- return prev_loc, prev_result.copy()
+ return prev_loc, copy.copy(prev_result)
del memo[peek_key]
- return prev_loc, prev_peek.copy()
+ return prev_loc, copy.copy(prev_peek)
# the match did get better: see if we can improve further
- if doActions:
+ if do_actions:
try:
memo[act_key] = super().parseImpl(instring, loc, True)
except ParseException as e:
@@ -5586,7 +5724,7 @@ class Forward(ParseElementEnhance):
ret <<= self
return ret
- def _setResultsName(self, name, list_all_matches=False):
+ def _setResultsName(self, name, list_all_matches=False) -> ParserElement:
# fmt: off
if (
__diag__.warn_name_set_on_empty_Forward
@@ -5612,7 +5750,7 @@ class Forward(ParseElementEnhance):
class TokenConverter(ParseElementEnhance):
"""
- Abstract subclass of :class:`ParseExpression`, for converting parsed results.
+ Abstract subclass of :class:`ParseElementEnhance`, for converting parsed results.
"""
def __init__(self, expr: Union[ParserElement, str], savelist=False):
@@ -5837,13 +5975,13 @@ class Suppress(TokenConverter):
expr = _PendingSkip(NoMatch())
super().__init__(expr)
- def __add__(self, other) -> "ParserElement":
+ def __add__(self, other) -> ParserElement:
if isinstance(self.expr, _PendingSkip):
return Suppress(SkipTo(other)) + other
return super().__add__(other)
- def __sub__(self, other) -> "ParserElement":
+ def __sub__(self, other) -> ParserElement:
if isinstance(self.expr, _PendingSkip):
return Suppress(SkipTo(other)) - other
@@ -5892,7 +6030,9 @@ def trace_parse_action(f: ParseAction) -> ParseAction:
try:
ret = f(*paArgs)
except Exception as exc:
- sys.stderr.write(f"<
{% endif %}
+
{{ body | safe }}
{% for diagram in diagrams %}
@@ -54,14 +55,23 @@ jinja2_template_source = """\
template = Template(jinja2_template_source)
-# Note: ideally this would be a dataclass, but we're supporting Python 3.5+ so we can't do this yet
-NamedDiagram = NamedTuple(
- "NamedDiagram",
- [("name", str), ("diagram", typing.Optional[railroad.DiagramItem]), ("index", int)],
-)
-"""
-A simple structure for associating a name with a railroad diagram
-"""
+
+def _collapse_verbose_regex(regex_str: str) -> str:
+ collapsed = pyparsing.Regex(r"#.*").suppress().transform_string(regex_str)
+ collapsed = re.sub(r"\s*\n\s*", "", collapsed)
+ return collapsed
+
+
+@dataclasses.dataclass
+class NamedDiagram:
+ """
+ A simple structure for associating a name with a railroad diagram
+ """
+
+ name: str
+ index: int
+ diagram: railroad.DiagramItem = None
+
T = TypeVar("T")
@@ -89,7 +99,7 @@ class AnnotatedItem(railroad.Group):
"""
def __init__(self, label: str, item):
- super().__init__(item=item, label="[{}]".format(label) if label else label)
+ super().__init__(item=item, label=f"[{label}]")
class EditablePartial(Generic[T]):
@@ -107,7 +117,7 @@ class EditablePartial(Generic[T]):
self.kwargs = kwargs
@classmethod
- def from_call(cls, func: Callable[..., T], *args, **kwargs) -> "EditablePartial[T]":
+ def from_call(cls, func: Callable[..., T], *args, **kwargs) -> EditablePartial[T]:
"""
If you call this function in the same way that you would call the constructor, it will store the arguments
as you expect. For example EditablePartial.from_call(Fraction, 1, 3)() == Fraction(1, 3)
@@ -134,7 +144,7 @@ class EditablePartial(Generic[T]):
return self.func(*args, **kwargs)
-def railroad_to_html(diagrams: List[NamedDiagram], embed=False, **kwargs) -> str:
+def railroad_to_html(diagrams: list[NamedDiagram], embed=False, **kwargs) -> str:
"""
Given a list of NamedDiagram, produce a single HTML string that visualises those diagrams
:params kwargs: kwargs to be passed in to the template
@@ -145,7 +155,7 @@ def railroad_to_html(diagrams: List[NamedDiagram], embed=False, **kwargs) -> str
continue
io = StringIO()
try:
- css = kwargs.get('css')
+ css = kwargs.get("css")
diagram.diagram.writeStandalone(io.write, css=css)
except AttributeError:
diagram.diagram.writeSvg(io.write)
@@ -157,7 +167,7 @@ def railroad_to_html(diagrams: List[NamedDiagram], embed=False, **kwargs) -> str
return template.render(diagrams=data, embed=embed, **kwargs)
-def resolve_partial(partial: "EditablePartial[T]") -> T:
+def resolve_partial(partial: EditablePartial[T]) -> T:
"""
Recursively resolves a collection of Partials into whatever type they are
"""
@@ -179,7 +189,7 @@ def to_railroad(
vertical: int = 3,
show_results_names: bool = False,
show_groups: bool = False,
-) -> List[NamedDiagram]:
+) -> list[NamedDiagram]:
"""
Convert a pyparsing element tree into a list of diagrams. This is the recommended entrypoint to diagram
creation if you want to access the Railroad tree before it is converted to HTML
@@ -243,40 +253,31 @@ def _should_vertical(
return len(_visible_exprs(exprs)) >= specification
+@dataclasses.dataclass
class ElementState:
"""
State recorded for an individual pyparsing Element
"""
- # Note: this should be a dataclass, but we have to support Python 3.5
- def __init__(
- self,
- element: pyparsing.ParserElement,
- converted: EditablePartial,
- parent: EditablePartial,
- number: int,
- name: str = None,
- parent_index: typing.Optional[int] = None,
- ):
- #: The pyparsing element that this represents
- self.element: pyparsing.ParserElement = element
- #: The name of the element
- self.name: typing.Optional[str] = name
- #: The output Railroad element in an unconverted state
- self.converted: EditablePartial = converted
- #: The parent Railroad element, which we store so that we can extract this if it's duplicated
- self.parent: EditablePartial = parent
- #: The order in which we found this element, used for sorting diagrams if this is extracted into a diagram
- self.number: int = number
- #: The index of this inside its parent
- self.parent_index: typing.Optional[int] = parent_index
- #: If true, we should extract this out into a subdiagram
- self.extract: bool = False
- #: If true, all of this element's children have been filled out
- self.complete: bool = False
+ #: The pyparsing element that this represents
+ element: pyparsing.ParserElement
+ #: The output Railroad element in an unconverted state
+ converted: EditablePartial
+ #: The parent Railroad element, which we store so that we can extract this if it's duplicated
+ parent: EditablePartial
+ #: The order in which we found this element, used for sorting diagrams if this is extracted into a diagram
+ number: int
+ #: The name of the element
+ name: str = None
+ #: The index of this inside its parent
+ parent_index: typing.Optional[int] = None
+ #: If true, we should extract this out into a subdiagram
+ extract: bool = False
+ #: If true, all of this element's children have been filled out
+ complete: bool = False
def mark_for_extraction(
- self, el_id: int, state: "ConverterState", name: str = None, force: bool = False
+ self, el_id: int, state: ConverterState, name: str = None, force: bool = False
):
"""
Called when this instance has been seen twice, and thus should eventually be extracted into a sub-diagram
@@ -312,16 +313,16 @@ class ConverterState:
def __init__(self, diagram_kwargs: typing.Optional[dict] = None):
#: A dictionary mapping ParserElements to state relating to them
- self._element_diagram_states: Dict[int, ElementState] = {}
+ self._element_diagram_states: dict[int, ElementState] = {}
#: A dictionary mapping ParserElement IDs to subdiagrams generated from them
- self.diagrams: Dict[int, EditablePartial[NamedDiagram]] = {}
+ self.diagrams: dict[int, EditablePartial[NamedDiagram]] = {}
#: The index of the next unnamed element
self.unnamed_index: int = 1
#: The index of the next element. This is used for sorting
self.index: int = 0
#: Shared kwargs that are used to customize the construction of diagrams
self.diagram_kwargs: dict = diagram_kwargs or {}
- self.extracted_diagram_names: Set[str] = set()
+ self.extracted_diagram_names: set[str] = set()
def __setitem__(self, key: int, value: ElementState):
self._element_diagram_states[key] = value
@@ -425,9 +426,11 @@ def _apply_diagram_item_enhancements(fn):
element_results_name = element.resultsName
if element_results_name:
# add "*" to indicate if this is a "list all results" name
- element_results_name += "" if element.modalResults else "*"
+ modal_tag = "" if element.modalResults else "*"
ret = EditablePartial.from_call(
- railroad.Group, item=ret, label=element_results_name
+ railroad.Group,
+ item=ret,
+ label=f"{repr(element_results_name)}{modal_tag}",
)
return ret
@@ -510,7 +513,7 @@ def _to_diagram_element(
# If the element isn't worth extracting, we always treat it as the first time we say it
if _worth_extracting(element):
- if el_id in lookup:
+ if el_id in lookup and lookup[el_id].name is not None:
# If we've seen this element exactly once before, we are only just now finding out that it's a duplicate,
# so we have to extract it into a new diagram.
looked_up = lookup[el_id]
@@ -534,7 +537,7 @@ def _to_diagram_element(
# (all will have the same name, and resultsName)
if not exprs:
return None
- if len(set((e.name, e.resultsName) for e in exprs)) == 1:
+ if len(set((e.name, e.resultsName) for e in exprs)) == 1 and len(exprs) > 2:
ret = EditablePartial.from_call(
railroad.OneOrMore, item="", repeat=str(len(exprs))
)
@@ -563,7 +566,7 @@ def _to_diagram_element(
if show_groups:
ret = EditablePartial.from_call(AnnotatedItem, label="", item="")
else:
- ret = EditablePartial.from_call(railroad.Group, label="", item="")
+ ret = EditablePartial.from_call(railroad.Sequence, items=[])
elif isinstance(element, pyparsing.TokenConverter):
label = type(element).__name__.lower()
if label == "tokenconverter":
@@ -573,8 +576,36 @@ def _to_diagram_element(
elif isinstance(element, pyparsing.Opt):
ret = EditablePartial.from_call(railroad.Optional, item="")
elif isinstance(element, pyparsing.OneOrMore):
- ret = EditablePartial.from_call(railroad.OneOrMore, item="")
+ if element.not_ender is not None:
+ args = [
+ parent,
+ lookup,
+ vertical,
+ index,
+ name_hint,
+ show_results_names,
+ show_groups,
+ ]
+ return _to_diagram_element(
+ (~element.not_ender.expr + element.expr)[1, ...].set_name(element.name),
+ *args,
+ )
+ ret = EditablePartial.from_call(railroad.OneOrMore, item=None)
elif isinstance(element, pyparsing.ZeroOrMore):
+ if element.not_ender is not None:
+ args = [
+ parent,
+ lookup,
+ vertical,
+ index,
+ name_hint,
+ show_results_names,
+ show_groups,
+ ]
+ return _to_diagram_element(
+ (~element.not_ender.expr + element.expr)[...].set_name(element.name),
+ *args,
+ )
ret = EditablePartial.from_call(railroad.ZeroOrMore, item="")
elif isinstance(element, pyparsing.Group):
ret = EditablePartial.from_call(
@@ -587,6 +618,11 @@ def _to_diagram_element(
ret = EditablePartial.from_call(railroad.Sequence, items=[])
elif len(exprs) > 0 and not element_results_name:
ret = EditablePartial.from_call(railroad.Group, item="", label=name)
+ elif isinstance(element, pyparsing.Regex):
+ patt = _collapse_verbose_regex(element.pattern)
+ element.pattern = patt
+ element._defaultName = None
+ ret = EditablePartial.from_call(railroad.Terminal, element.defaultName)
elif len(exprs) > 0:
ret = EditablePartial.from_call(railroad.Sequence, items=[])
else:
diff --git a/lib/pyparsing/exceptions.py b/lib/pyparsing/exceptions.py
index 1aaea56f..57a1579d 100644
--- a/lib/pyparsing/exceptions.py
+++ b/lib/pyparsing/exceptions.py
@@ -1,17 +1,20 @@
# exceptions.py
+from __future__ import annotations
+import copy
import re
import sys
import typing
+from functools import cached_property
+from .unicode import pyparsing_unicode as ppu
from .util import (
+ _collapse_string_to_ranges,
col,
line,
lineno,
- _collapse_string_to_ranges,
replaced_by_pep8,
)
-from .unicode import pyparsing_unicode as ppu
class _ExceptionWordUnicodeSet(
@@ -31,7 +34,7 @@ class ParseBaseException(Exception):
msg: str
pstr: str
parser_element: typing.Any # "ParserElement"
- args: typing.Tuple[str, int, typing.Optional[str]]
+ args: tuple[str, int, typing.Optional[str]]
__slots__ = (
"loc",
@@ -50,18 +53,17 @@ class ParseBaseException(Exception):
msg: typing.Optional[str] = None,
elem=None,
):
- self.loc = loc
if msg is None:
- self.msg = pstr
- self.pstr = ""
- else:
- self.msg = msg
- self.pstr = pstr
+ msg, pstr = pstr, ""
+
+ self.loc = loc
+ self.msg = msg
+ self.pstr = pstr
self.parser_element = elem
self.args = (pstr, loc, msg)
@staticmethod
- def explain_exception(exc, depth=16):
+ def explain_exception(exc: Exception, depth: int = 16) -> str:
"""
Method to take an exception and translate the Python internal traceback into a list
of the pyparsing expressions that caused the exception to be raised.
@@ -82,17 +84,17 @@ class ParseBaseException(Exception):
if depth is None:
depth = sys.getrecursionlimit()
- ret = []
+ ret: list[str] = []
if isinstance(exc, ParseBaseException):
ret.append(exc.line)
- ret.append(" " * (exc.column - 1) + "^")
+ ret.append(f"{' ' * (exc.column - 1)}^")
ret.append(f"{type(exc).__name__}: {exc}")
- if depth <= 0:
+ if depth <= 0 or exc.__traceback__ is None:
return "\n".join(ret)
callers = inspect.getinnerframes(exc.__traceback__, context=depth)
- seen = set()
+ seen: set[int] = set()
for ff in callers[-depth:]:
frm = ff[0]
@@ -125,41 +127,58 @@ class ParseBaseException(Exception):
return "\n".join(ret)
@classmethod
- def _from_exception(cls, pe):
+ def _from_exception(cls, pe) -> ParseBaseException:
"""
internal factory method to simplify creating one type of ParseException
from another - avoids having __init__ signature conflicts among subclasses
"""
return cls(pe.pstr, pe.loc, pe.msg, pe.parser_element)
- @property
+ @cached_property
def line(self) -> str:
"""
Return the line of text where the exception occurred.
"""
return line(self.loc, self.pstr)
- @property
+ @cached_property
def lineno(self) -> int:
"""
Return the 1-based line number of text where the exception occurred.
"""
return lineno(self.loc, self.pstr)
- @property
+ @cached_property
def col(self) -> int:
"""
Return the 1-based column on the line of text where the exception occurred.
"""
return col(self.loc, self.pstr)
- @property
+ @cached_property
def column(self) -> int:
"""
Return the 1-based column on the line of text where the exception occurred.
"""
return col(self.loc, self.pstr)
+ @cached_property
+ def found(self) -> str:
+ if not self.pstr:
+ return ""
+
+ if self.loc >= len(self.pstr):
+ return "end of text"
+
+ # pull out next word at error location
+ found_match = _exception_word_extractor.match(self.pstr, self.loc)
+ if found_match is not None:
+ found_text = found_match.group(0)
+ else:
+ found_text = self.pstr[self.loc : self.loc + 1]
+
+ return repr(found_text).replace(r"\\", "\\")
+
# pre-PEP8 compatibility
@property
def parserElement(self):
@@ -169,21 +188,15 @@ class ParseBaseException(Exception):
def parserElement(self, elem):
self.parser_element = elem
+ def copy(self):
+ return copy.copy(self)
+
+ def formatted_message(self) -> str:
+ found_phrase = f", found {self.found}" if self.found else ""
+ return f"{self.msg}{found_phrase} (at char {self.loc}), (line:{self.lineno}, col:{self.column})"
+
def __str__(self) -> str:
- if self.pstr:
- if self.loc >= len(self.pstr):
- foundstr = ", found end of text"
- else:
- # pull out next word at error location
- found_match = _exception_word_extractor.match(self.pstr, self.loc)
- if found_match is not None:
- found = found_match.group(0)
- else:
- found = self.pstr[self.loc : self.loc + 1]
- foundstr = (", found %r" % found).replace(r"\\", "\\")
- else:
- foundstr = ""
- return f"{self.msg}{foundstr} (at char {self.loc}), (line:{self.lineno}, col:{self.column})"
+ return self.formatted_message()
def __repr__(self):
return str(self)
@@ -199,12 +212,10 @@ class ParseBaseException(Exception):
line_str = self.line
line_column = self.column - 1
if markerString:
- line_str = "".join(
- (line_str[:line_column], markerString, line_str[line_column:])
- )
+ line_str = f"{line_str[:line_column]}{markerString}{line_str[line_column:]}"
return line_str.strip()
- def explain(self, depth=16) -> str:
+ def explain(self, depth: int = 16) -> str:
"""
Method to translate the Python internal traceback into a list
of the pyparsing expressions that caused the exception to be raised.
@@ -245,6 +256,7 @@ class ParseBaseException(Exception):
"""
return self.explain_exception(self, depth)
+ # Compatibility synonyms
# fmt: off
markInputline = replaced_by_pep8("markInputline", mark_input_line)
# fmt: on
@@ -291,6 +303,8 @@ class RecursiveGrammarException(Exception):
Exception thrown by :class:`ParserElement.validate` if the
grammar could be left-recursive; parser may need to enable
left recursion using :class:`ParserElement.enable_left_recursion
`
+
+ Deprecated: only used by deprecated method ParserElement.validate.
"""
def __init__(self, parseElementList):
diff --git a/lib/pyparsing/helpers.py b/lib/pyparsing/helpers.py
index dcfdb8fe..d2bd05f3 100644
--- a/lib/pyparsing/helpers.py
+++ b/lib/pyparsing/helpers.py
@@ -1,5 +1,6 @@
# helpers.py
import html.entities
+import operator
import re
import sys
import typing
@@ -10,6 +11,7 @@ from .util import (
_bslash,
_flatten,
_escape_regex_range_chars,
+ make_compressed_re,
replaced_by_pep8,
)
@@ -203,15 +205,15 @@ def one_of(
)
if caseless:
- isequal = lambda a, b: a.upper() == b.upper()
+ is_equal = lambda a, b: a.upper() == b.upper()
masks = lambda a, b: b.upper().startswith(a.upper())
- parseElementClass = CaselessKeyword if asKeyword else CaselessLiteral
+ parse_element_class = CaselessKeyword if asKeyword else CaselessLiteral
else:
- isequal = lambda a, b: a == b
+ is_equal = operator.eq
masks = lambda a, b: b.startswith(a)
- parseElementClass = Keyword if asKeyword else Literal
+ parse_element_class = Keyword if asKeyword else Literal
- symbols: List[str] = []
+ symbols: list[str]
if isinstance(strs, str_type):
strs = typing.cast(str, strs)
symbols = strs.split()
@@ -224,20 +226,19 @@ def one_of(
# reorder given symbols to take care to avoid masking longer choices with shorter ones
# (but only if the given symbols are not just single characters)
- if any(len(sym) > 1 for sym in symbols):
- i = 0
- while i < len(symbols) - 1:
- cur = symbols[i]
- for j, other in enumerate(symbols[i + 1 :]):
- if isequal(other, cur):
- del symbols[i + j + 1]
- break
- if masks(cur, other):
- del symbols[i + j + 1]
- symbols.insert(i, other)
- break
- else:
- i += 1
+ i = 0
+ while i < len(symbols) - 1:
+ cur = symbols[i]
+ for j, other in enumerate(symbols[i + 1 :]):
+ if is_equal(other, cur):
+ del symbols[i + j + 1]
+ break
+ if len(other) > len(cur) and masks(cur, other):
+ del symbols[i + j + 1]
+ symbols.insert(i, other)
+ break
+ else:
+ i += 1
if useRegex:
re_flags: int = re.IGNORECASE if caseless else 0
@@ -269,7 +270,7 @@ def one_of(
)
# last resort, just use MatchFirst
- return MatchFirst(parseElementClass(sym) for sym in symbols).set_name(
+ return MatchFirst(parse_element_class(sym) for sym in symbols).set_name(
" | ".join(symbols)
)
@@ -602,7 +603,7 @@ def _makeTags(tagStr, xml, suppress_LT=Suppress("<"), suppress_GT=Suppress(">"))
def make_html_tags(
tag_str: Union[str, ParserElement]
-) -> Tuple[ParserElement, ParserElement]:
+) -> tuple[ParserElement, ParserElement]:
"""Helper to construct opening and closing tag expressions for HTML,
given a tag name. Matches tags in either upper or lower case,
attributes with namespaces and with quoted or unquoted values.
@@ -629,7 +630,7 @@ def make_html_tags(
def make_xml_tags(
tag_str: Union[str, ParserElement]
-) -> Tuple[ParserElement, ParserElement]:
+) -> tuple[ParserElement, ParserElement]:
"""Helper to construct opening and closing tag expressions for XML,
given a tag name. Matches tags only in the given upper/lower case.
@@ -645,9 +646,12 @@ any_open_tag, any_close_tag = make_html_tags(
)
_htmlEntityMap = {k.rstrip(";"): v for k, v in html.entities.html5.items()}
-common_html_entity = Regex("&(?P" + "|".join(_htmlEntityMap) + ");").set_name(
- "common HTML entity"
+_most_common_entities = "nbsp lt gt amp quot apos cent pound euro copy".replace(
+ " ", "|"
)
+common_html_entity = Regex(
+ lambda: f"&(?P{_most_common_entities}|{make_compressed_re(_htmlEntityMap)});"
+).set_name("common HTML entity")
def replace_html_entity(s, l, t):
@@ -664,16 +668,16 @@ class OpAssoc(Enum):
InfixNotationOperatorArgType = Union[
- ParserElement, str, Tuple[Union[ParserElement, str], Union[ParserElement, str]]
+ ParserElement, str, tuple[Union[ParserElement, str], Union[ParserElement, str]]
]
InfixNotationOperatorSpec = Union[
- Tuple[
+ tuple[
InfixNotationOperatorArgType,
int,
OpAssoc,
typing.Optional[ParseAction],
],
- Tuple[
+ tuple[
InfixNotationOperatorArgType,
int,
OpAssoc,
@@ -683,7 +687,7 @@ InfixNotationOperatorSpec = Union[
def infix_notation(
base_expr: ParserElement,
- op_list: List[InfixNotationOperatorSpec],
+ op_list: list[InfixNotationOperatorSpec],
lpar: Union[str, ParserElement] = Suppress("("),
rpar: Union[str, ParserElement] = Suppress(")"),
) -> ParserElement:
@@ -782,9 +786,12 @@ def infix_notation(
# if lpar and rpar are not suppressed, wrap in group
if not (isinstance(lpar, Suppress) and isinstance(rpar, Suppress)):
- lastExpr = base_expr | Group(lpar + ret + rpar)
+ lastExpr = base_expr | Group(lpar + ret + rpar).set_name(
+ f"nested_{base_expr.name}"
+ )
else:
- lastExpr = base_expr | (lpar + ret + rpar)
+ lastExpr = base_expr | (lpar + ret + rpar).set_name(f"nested_{base_expr.name}")
+ root_expr = lastExpr
arity: int
rightLeftAssoc: opAssoc
@@ -855,6 +862,7 @@ def infix_notation(
thisExpr <<= (matchExpr | lastExpr).setName(term_name)
lastExpr = thisExpr
ret <<= lastExpr
+ root_expr.set_name("base_expr")
return ret
@@ -1028,7 +1036,7 @@ python_style_comment = Regex(r"#.*").set_name("Python style comment")
# build list of built-in expressions, for future reference if a global default value
# gets updated
-_builtin_exprs: List[ParserElement] = [
+_builtin_exprs: list[ParserElement] = [
v for v in vars().values() if isinstance(v, ParserElement)
]
@@ -1049,7 +1057,7 @@ def delimited_list(
)
-# pre-PEP8 compatible names
+# Compatibility synonyms
# fmt: off
opAssoc = OpAssoc
anyOpenTag = any_open_tag
diff --git a/lib/pyparsing/results.py b/lib/pyparsing/results.py
index 3e5fe208..24584783 100644
--- a/lib/pyparsing/results.py
+++ b/lib/pyparsing/results.py
@@ -1,25 +1,30 @@
# results.py
+from __future__ import annotations
+
+import collections
from collections.abc import (
MutableMapping,
Mapping,
MutableSequence,
Iterator,
- Sequence,
- Container,
+ Iterable,
)
import pprint
-from typing import Tuple, Any, Dict, Set, List
+from typing import Any
-str_type: Tuple[type, ...] = (str, bytes)
+from .util import replaced_by_pep8
+
+
+str_type: tuple[type, ...] = (str, bytes)
_generator_type = type((_ for _ in ()))
class _ParseResultsWithOffset:
- tup: Tuple["ParseResults", int]
+ tup: tuple[ParseResults, int]
__slots__ = ["tup"]
- def __init__(self, p1: "ParseResults", p2: int):
- self.tup: Tuple[ParseResults, int] = (p1, p2)
+ def __init__(self, p1: ParseResults, p2: int):
+ self.tup: tuple[ParseResults, int] = (p1, p2)
def __getitem__(self, i):
return self.tup[i]
@@ -77,14 +82,14 @@ class ParseResults:
- year: '1999'
"""
- _null_values: Tuple[Any, ...] = (None, [], ())
+ _null_values: tuple[Any, ...] = (None, [], ())
_name: str
- _parent: "ParseResults"
- _all_names: Set[str]
+ _parent: ParseResults
+ _all_names: set[str]
_modal: bool
- _toklist: List[Any]
- _tokdict: Dict[str, Any]
+ _toklist: list[Any]
+ _tokdict: dict[str, Any]
__slots__ = (
"_name",
@@ -170,8 +175,8 @@ class ParseResults:
# constructor as small and fast as possible
def __init__(
self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance
- ):
- self._tokdict: Dict[str, _ParseResultsWithOffset]
+ ) -> None:
+ self._tokdict: dict[str, _ParseResultsWithOffset]
self._modal = modal
if name is None or name == "":
@@ -224,7 +229,7 @@ class ParseResults:
self._toklist[k] = v
sub = v
else:
- self._tokdict[k] = self._tokdict.get(k, list()) + [
+ self._tokdict[k] = self._tokdict.get(k, []) + [
_ParseResultsWithOffset(v, 0)
]
sub = v
@@ -441,12 +446,12 @@ class ParseResults:
raise AttributeError(name)
return ""
- def __add__(self, other: "ParseResults") -> "ParseResults":
+ def __add__(self, other: ParseResults) -> ParseResults:
ret = self.copy()
ret += other
return ret
- def __iadd__(self, other: "ParseResults") -> "ParseResults":
+ def __iadd__(self, other: ParseResults) -> ParseResults:
if not other:
return self
@@ -468,7 +473,7 @@ class ParseResults:
self._all_names |= other._all_names
return self
- def __radd__(self, other) -> "ParseResults":
+ def __radd__(self, other) -> ParseResults:
if isinstance(other, int) and other == 0:
# useful for merging many ParseResults using sum() builtin
return self.copy()
@@ -502,9 +507,10 @@ class ParseResults:
out.append(str(item))
return out
- def as_list(self) -> list:
+ def as_list(self, *, flatten: bool = False) -> list:
"""
Returns the parse results as a nested list of matching tokens, all converted to strings.
+ If flatten is True, all the nesting levels in the returned list are collapsed.
Example::
@@ -517,10 +523,22 @@ class ParseResults:
result_list = result.as_list()
print(type(result_list), result_list) # -> ['sldkj', 'lsdkj', 'sldkj']
"""
- return [
- res.as_list() if isinstance(res, ParseResults) else res
- for res in self._toklist
- ]
+ def flattened(pr):
+ to_visit = collections.deque([*self])
+ while to_visit:
+ to_do = to_visit.popleft()
+ if isinstance(to_do, ParseResults):
+ to_visit.extendleft(to_do[::-1])
+ else:
+ yield to_do
+
+ if flatten:
+ return [*flattened(self)]
+ else:
+ return [
+ res.as_list() if isinstance(res, ParseResults) else res
+ for res in self._toklist
+ ]
def as_dict(self) -> dict:
"""
@@ -551,7 +569,7 @@ class ParseResults:
return dict((k, to_item(v)) for k, v in self.items())
- def copy(self) -> "ParseResults":
+ def copy(self) -> ParseResults:
"""
Returns a new shallow copy of a :class:`ParseResults` object. `ParseResults`
items contained within the source are shared with the copy. Use
@@ -565,7 +583,7 @@ class ParseResults:
ret._name = self._name
return ret
- def deepcopy(self) -> "ParseResults":
+ def deepcopy(self) -> ParseResults:
"""
Returns a new deep copy of a :class:`ParseResults` object.
"""
@@ -573,20 +591,20 @@ class ParseResults:
# replace values with copies if they are of known mutable types
for i, obj in enumerate(self._toklist):
if isinstance(obj, ParseResults):
- self._toklist[i] = obj.deepcopy()
+ ret._toklist[i] = obj.deepcopy()
elif isinstance(obj, (str, bytes)):
pass
elif isinstance(obj, MutableMapping):
- self._toklist[i] = dest = type(obj)()
+ ret._toklist[i] = dest = type(obj)()
for k, v in obj.items():
dest[k] = v.deepcopy() if isinstance(v, ParseResults) else v
- elif isinstance(obj, Container):
- self._toklist[i] = type(obj)(
- v.deepcopy() if isinstance(v, ParseResults) else v for v in obj
+ elif isinstance(obj, Iterable):
+ ret._toklist[i] = type(obj)(
+ v.deepcopy() if isinstance(v, ParseResults) else v for v in obj # type: ignore[call-arg]
)
return ret
- def get_name(self):
+ def get_name(self) -> str | None:
r"""
Returns the results name for this token expression. Useful when several
different expressions might match at a particular location.
@@ -614,7 +632,7 @@ class ParseResults:
if self._name:
return self._name
elif self._parent:
- par: "ParseResults" = self._parent
+ par: ParseResults = self._parent
parent_tokdict_items = par._tokdict.items()
return next(
(
@@ -759,7 +777,7 @@ class ParseResults:
return dir(type(self)) + list(self.keys())
@classmethod
- def from_dict(cls, other, name=None) -> "ParseResults":
+ def from_dict(cls, other, name=None) -> ParseResults:
"""
Helper classmethod to construct a ``ParseResults`` from a ``dict``, preserving the
name-value relations as results names. If an optional ``name`` argument is
diff --git a/lib/pyparsing/testing.py b/lib/pyparsing/testing.py
index 5654d47d..836b2f86 100644
--- a/lib/pyparsing/testing.py
+++ b/lib/pyparsing/testing.py
@@ -257,10 +257,14 @@ class pyparsing_test:
eol_mark: str = "|",
mark_spaces: typing.Optional[str] = None,
mark_control: typing.Optional[str] = None,
+ *,
+ indent: typing.Union[str, int] = "",
+ base_1: bool = True,
) -> str:
"""
Helpful method for debugging a parser - prints a string with line and column numbers.
- (Line and column numbers are 1-based.)
+ (Line and column numbers are 1-based by default - if debugging a parse action,
+ pass base_1=False, to correspond to the loc value passed to the parse action.)
:param s: tuple(bool, str - string to be printed with line and column numbers
:param start_line: int - (optional) starting line number in s to print (default=1)
@@ -273,11 +277,18 @@ class pyparsing_test:
- "unicode" - replaces control chars with Unicode symbols, such as "␍" and "␊"
- any single character string - replace control characters with given string
- None (default) - string is displayed as-is
+ :param indent: str | int - (optional) string to indent with line and column numbers; if an int
+ is passed, converted to " " * indent
+ :param base_1: bool - (optional) whether to label string using base 1; if False, string will be
+ labeled based at 0 (default=True)
:return: str - input string with leading line numbers and column number headers
"""
if expand_tabs:
s = s.expandtabs()
+ if isinstance(indent, int):
+ indent = " " * indent
+ indent = indent.expandtabs()
if mark_control is not None:
mark_control = typing.cast(str, mark_control)
if mark_control == "unicode":
@@ -300,46 +311,52 @@ class pyparsing_test:
else:
s = s.replace(" ", mark_spaces)
if start_line is None:
- start_line = 1
+ start_line = 0
if end_line is None:
end_line = len(s)
end_line = min(end_line, len(s))
- start_line = min(max(1, start_line), end_line)
+ start_line = min(max(0, start_line), end_line)
if mark_control != "unicode":
- s_lines = s.splitlines()[start_line - 1 : end_line]
+ s_lines = s.splitlines()[start_line - base_1 : end_line]
else:
- s_lines = [line + "␊" for line in s.split("␊")[start_line - 1 : end_line]]
+ s_lines = [
+ line + "␊" for line in s.split("␊")[start_line - base_1 : end_line]
+ ]
if not s_lines:
return ""
lineno_width = len(str(end_line))
max_line_len = max(len(line) for line in s_lines)
- lead = " " * (lineno_width + 1)
+ lead = indent + " " * (lineno_width + 1)
if max_line_len >= 99:
header0 = (
lead
+ + ("" if base_1 else " ")
+ "".join(
f"{' ' * 99}{(i + 1) % 100}"
- for i in range(max(max_line_len // 100, 1))
+ for i in range(1 if base_1 else 0, max(max_line_len // 100, 1))
)
+ "\n"
)
else:
header0 = ""
header1 = (
- header0
+ ("" if base_1 else " ")
+ lead
+ "".join(f" {(i + 1) % 10}" for i in range(-(-max_line_len // 10)))
+ "\n"
)
- header2 = lead + "1234567890" * (-(-max_line_len // 10)) + "\n"
+ digits = "1234567890"
+ header2 = (
+ lead + ("" if base_1 else "0") + digits * (-(-max_line_len // 10)) + "\n"
+ )
return (
header1
+ header2
+ "\n".join(
- f"{i:{lineno_width}d}:{line}{eol_mark}"
- for i, line in enumerate(s_lines, start=start_line)
+ f"{indent}{i:{lineno_width}d}:{line}{eol_mark}"
+ for i, line in enumerate(s_lines, start=start_line + base_1)
)
+ "\n"
)
diff --git a/lib/pyparsing/unicode.py b/lib/pyparsing/unicode.py
index 426b8b23..066486c2 100644
--- a/lib/pyparsing/unicode.py
+++ b/lib/pyparsing/unicode.py
@@ -2,7 +2,7 @@
import sys
from itertools import filterfalse
-from typing import List, Tuple, Union
+from typing import Union
class _lazyclassproperty:
@@ -25,7 +25,7 @@ class _lazyclassproperty:
return cls._intern[attrname]
-UnicodeRangeList = List[Union[Tuple[int, int], Tuple[int]]]
+UnicodeRangeList = list[Union[tuple[int, int], tuple[int]]]
class unicode_set:
@@ -53,51 +53,51 @@ class unicode_set:
_ranges: UnicodeRangeList = []
@_lazyclassproperty
- def _chars_for_ranges(cls):
- ret = []
- for cc in cls.__mro__:
+ def _chars_for_ranges(cls) -> list[str]:
+ ret: list[int] = []
+ for cc in cls.__mro__: # type: ignore[attr-defined]
if cc is unicode_set:
break
for rr in getattr(cc, "_ranges", ()):
ret.extend(range(rr[0], rr[-1] + 1))
- return [chr(c) for c in sorted(set(ret))]
+ return sorted(chr(c) for c in set(ret))
@_lazyclassproperty
- def printables(cls):
+ def printables(cls) -> str:
"""all non-whitespace characters in this range"""
return "".join(filterfalse(str.isspace, cls._chars_for_ranges))
@_lazyclassproperty
- def alphas(cls):
+ def alphas(cls) -> str:
"""all alphabetic characters in this range"""
return "".join(filter(str.isalpha, cls._chars_for_ranges))
@_lazyclassproperty
- def nums(cls):
+ def nums(cls) -> str:
"""all numeric digit characters in this range"""
return "".join(filter(str.isdigit, cls._chars_for_ranges))
@_lazyclassproperty
- def alphanums(cls):
+ def alphanums(cls) -> str:
"""all alphanumeric characters in this range"""
return cls.alphas + cls.nums
@_lazyclassproperty
- def identchars(cls):
+ def identchars(cls) -> str:
"""all characters in this range that are valid identifier characters, plus underscore '_'"""
return "".join(
sorted(
- set(
- "".join(filter(str.isidentifier, cls._chars_for_ranges))
- + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµº"
- + "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ"
- + "_"
+ set(filter(str.isidentifier, cls._chars_for_ranges))
+ | set(
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµº"
+ "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ"
+ "_"
)
)
)
@_lazyclassproperty
- def identbodychars(cls):
+ def identbodychars(cls) -> str:
"""
all characters in this range that are valid identifier body characters,
plus the digits 0-9, and · (Unicode MIDDLE DOT)
@@ -105,7 +105,9 @@ class unicode_set:
identifier_chars = set(
c for c in cls._chars_for_ranges if ("_" + c).isidentifier()
)
- return "".join(sorted(identifier_chars | set(cls.identchars + "0123456789·")))
+ return "".join(
+ sorted(identifier_chars | set(cls.identchars) | set("0123456789·"))
+ )
@_lazyclassproperty
def identifier(cls):
diff --git a/lib/pyparsing/util.py b/lib/pyparsing/util.py
index 4ae018a9..1487019c 100644
--- a/lib/pyparsing/util.py
+++ b/lib/pyparsing/util.py
@@ -1,11 +1,11 @@
# util.py
-import inspect
-import warnings
-import types
-import collections
-import itertools
+import contextlib
from functools import lru_cache, wraps
-from typing import Callable, List, Union, Iterable, TypeVar, cast
+import inspect
+import itertools
+import types
+from typing import Callable, Union, Iterable, TypeVar, cast
+import warnings
_bslash = chr(92)
C = TypeVar("C", bound=Callable)
@@ -14,8 +14,8 @@ C = TypeVar("C", bound=Callable)
class __config_flags:
"""Internal class for defining compatibility and debugging flags"""
- _all_names: List[str] = []
- _fixed_names: List[str] = []
+ _all_names: list[str] = []
+ _fixed_names: list[str] = []
_type_desc = "configuration"
@classmethod
@@ -100,27 +100,24 @@ class _UnboundedCache:
class _FifoCache:
def __init__(self, size):
- self.not_in_cache = not_in_cache = object()
cache = {}
- keyring = [object()] * size
+ self.size = size
+ self.not_in_cache = not_in_cache = object()
cache_get = cache.get
cache_pop = cache.pop
- keyiter = itertools.cycle(range(size))
def get(_, key):
return cache_get(key, not_in_cache)
def set_(_, key, value):
cache[key] = value
- i = next(keyiter)
- cache_pop(keyring[i], None)
- keyring[i] = key
+ while len(cache) > size:
+ # pop oldest element in cache by getting the first key
+ cache_pop(next(iter(cache)))
def clear(_):
cache.clear()
- keyring[:] = [object()] * size
- self.size = size
self.get = types.MethodType(get, self)
self.set = types.MethodType(set_, self)
self.clear = types.MethodType(clear, self)
@@ -137,13 +134,13 @@ class LRUMemo:
def __init__(self, capacity):
self._capacity = capacity
self._active = {}
- self._memory = collections.OrderedDict()
+ self._memory = {}
def __getitem__(self, key):
try:
return self._active[key]
except KeyError:
- self._memory.move_to_end(key)
+ self._memory[key] = self._memory.pop(key)
return self._memory[key]
def __setitem__(self, key, value):
@@ -156,8 +153,9 @@ class LRUMemo:
except KeyError:
pass
else:
- while len(self._memory) >= self._capacity:
- self._memory.popitem(last=False)
+ oldest_keys = list(self._memory)[: -(self._capacity + 1)]
+ for key_to_delete in oldest_keys:
+ self._memory.pop(key_to_delete)
self._memory[key] = value
def clear(self):
@@ -183,60 +181,182 @@ def _escape_regex_range_chars(s: str) -> str:
return str(s)
+class _GroupConsecutive:
+ """
+ Used as a callable `key` for itertools.groupby to group
+ characters that are consecutive:
+ itertools.groupby("abcdejkmpqrs", key=IsConsecutive())
+ yields:
+ (0, iter(['a', 'b', 'c', 'd', 'e']))
+ (1, iter(['j', 'k']))
+ (2, iter(['m']))
+ (3, iter(['p', 'q', 'r', 's']))
+ """
+ def __init__(self):
+ self.prev = 0
+ self.counter = itertools.count()
+ self.value = -1
+
+ def __call__(self, char: str) -> int:
+ c_int = ord(char)
+ self.prev, prev = c_int, self.prev
+ if c_int - prev > 1:
+ self.value = next(self.counter)
+ return self.value
+
+
def _collapse_string_to_ranges(
s: Union[str, Iterable[str]], re_escape: bool = True
) -> str:
- def is_consecutive(c):
- c_int = ord(c)
- is_consecutive.prev, prev = c_int, is_consecutive.prev
- if c_int - prev > 1:
- is_consecutive.value = next(is_consecutive.counter)
- return is_consecutive.value
+ r"""
+ Take a string or list of single-character strings, and return
+ a string of the consecutive characters in that string collapsed
+ into groups, as might be used in a regular expression '[a-z]'
+ character set:
+ 'a' -> 'a' -> '[a]'
+ 'bc' -> 'bc' -> '[bc]'
+ 'defgh' -> 'd-h' -> '[d-h]'
+ 'fdgeh' -> 'd-h' -> '[d-h]'
+ 'jklnpqrtu' -> 'j-lnp-rtu' -> '[j-lnp-rtu]'
+ Duplicates get collapsed out:
+ 'aaa' -> 'a' -> '[a]'
+ 'bcbccb' -> 'bc' -> '[bc]'
+ 'defghhgf' -> 'd-h' -> '[d-h]'
+ 'jklnpqrjjjtu' -> 'j-lnp-rtu' -> '[j-lnp-rtu]'
+ Spaces are preserved:
+ 'ab c' -> ' a-c' -> '[ a-c]'
+ Characters that are significant when defining regex ranges
+ get escaped:
+ 'acde[]-' -> r'\-\[\]ac-e' -> r'[\-\[\]ac-e]'
+ """
- is_consecutive.prev = 0 # type: ignore [attr-defined]
- is_consecutive.counter = itertools.count() # type: ignore [attr-defined]
- is_consecutive.value = -1 # type: ignore [attr-defined]
+ # Developer notes:
+ # - Do not optimize this code assuming that the given input string
+ # or internal lists will be short (such as in loading generators into
+ # lists to make it easier to find the last element); this method is also
+ # used to generate regex ranges for character sets in the pyparsing.unicode
+ # classes, and these can be _very_ long lists of strings
- def escape_re_range_char(c):
+ def escape_re_range_char(c: str) -> str:
return "\\" + c if c in r"\^-][" else c
- def no_escape_re_range_char(c):
+ def no_escape_re_range_char(c: str) -> str:
return c
if not re_escape:
escape_re_range_char = no_escape_re_range_char
ret = []
- s = "".join(sorted(set(s)))
- if len(s) > 3:
- for _, chars in itertools.groupby(s, key=is_consecutive):
+
+ # reduce input string to remove duplicates, and put in sorted order
+ s_chars: list[str] = sorted(set(s))
+
+ if len(s_chars) > 2:
+ # find groups of characters that are consecutive (can be collapsed
+ # down to "-")
+ for _, chars in itertools.groupby(s_chars, key=_GroupConsecutive()):
+ # _ is unimportant, is just used to identify groups
+ # chars is an iterator of one or more consecutive characters
+ # that comprise the current group
first = last = next(chars)
- last = collections.deque(
- itertools.chain(iter([last]), chars), maxlen=1
- ).pop()
+ with contextlib.suppress(ValueError):
+ *_, last = chars
+
if first == last:
+ # there was only a single char in this group
ret.append(escape_re_range_char(first))
+
+ elif last == chr(ord(first) + 1):
+ # there were only 2 characters in this group
+ # 'a','b' -> 'ab'
+ ret.append(f"{escape_re_range_char(first)}{escape_re_range_char(last)}")
+
else:
- sep = "" if ord(last) == ord(first) + 1 else "-"
+ # there were > 2 characters in this group, make into a range
+ # 'c','d','e' -> 'c-e'
ret.append(
- f"{escape_re_range_char(first)}{sep}{escape_re_range_char(last)}"
+ f"{escape_re_range_char(first)}-{escape_re_range_char(last)}"
)
else:
- ret = [escape_re_range_char(c) for c in s]
+ # only 1 or 2 chars were given to form into groups
+ # 'a' -> ['a']
+ # 'bc' -> ['b', 'c']
+ # 'dg' -> ['d', 'g']
+ # no need to list them with "-", just return as a list
+ # (after escaping)
+ ret = [escape_re_range_char(c) for c in s_chars]
return "".join(ret)
-def _flatten(ll: list) -> list:
+def _flatten(ll: Iterable) -> list:
ret = []
- for i in ll:
- if isinstance(i, list):
- ret.extend(_flatten(i))
+ to_visit = [*ll]
+ while to_visit:
+ i = to_visit.pop(0)
+ if isinstance(i, Iterable) and not isinstance(i, str):
+ to_visit[:0] = i
else:
ret.append(i)
return ret
+def make_compressed_re(
+ word_list: Iterable[str], max_level: int = 2, _level: int = 1
+) -> str:
+ """
+ Create a regular expression string from a list of words, collapsing by common
+ prefixes and optional suffixes.
+
+ Calls itself recursively to build nested sublists for each group of suffixes
+ that have a shared prefix.
+ """
+
+ def get_suffixes_from_common_prefixes(namelist: list[str]):
+ if len(namelist) > 1:
+ for prefix, suffixes in itertools.groupby(namelist, key=lambda s: s[:1]):
+ yield prefix, sorted([s[1:] for s in suffixes], key=len, reverse=True)
+ else:
+ yield namelist[0][0], [namelist[0][1:]]
+
+ if max_level == 0:
+ return "|".join(sorted(word_list, key=len, reverse=True))
+
+ ret = []
+ sep = ""
+ for initial, suffixes in get_suffixes_from_common_prefixes(sorted(word_list)):
+ ret.append(sep)
+ sep = "|"
+
+ trailing = ""
+ if "" in suffixes:
+ trailing = "?"
+ suffixes.remove("")
+
+ if len(suffixes) > 1:
+ if all(len(s) == 1 for s in suffixes):
+ ret.append(f"{initial}[{''.join(suffixes)}]{trailing}")
+ else:
+ if _level < max_level:
+ suffix_re = make_compressed_re(
+ sorted(suffixes), max_level, _level + 1
+ )
+ ret.append(f"{initial}({suffix_re}){trailing}")
+ else:
+ suffixes.sort(key=len, reverse=True)
+ ret.append(f"{initial}({'|'.join(suffixes)}){trailing}")
+ else:
+ if suffixes:
+ suffix = suffixes[0]
+ if len(suffix) > 1 and trailing:
+ ret.append(f"{initial}({suffix}){trailing}")
+ else:
+ ret.append(f"{initial}{suffix}{trailing}")
+ else:
+ ret.append(initial)
+ return "".join(ret)
+
+
def replaced_by_pep8(compat_name: str, fn: C) -> C:
# In a future version, uncomment the code in the internal _inner() functions
# to begin emitting DeprecationWarnings.
@@ -246,7 +366,7 @@ def replaced_by_pep8(compat_name: str, fn: C) -> C:
# (Presence of 'self' arg in signature is used by explain_exception() methods, so we take
# some extra steps to add it if present in decorated function.)
- if "self" == list(inspect.signature(fn).parameters)[0]:
+ if ["self"] == list(inspect.signature(fn).parameters)[:1]:
@wraps(fn)
def _inner(self, *args, **kwargs):
@@ -268,10 +388,10 @@ def replaced_by_pep8(compat_name: str, fn: C) -> C:
_inner.__name__ = compat_name
_inner.__annotations__ = fn.__annotations__
if isinstance(fn, types.FunctionType):
- _inner.__kwdefaults__ = fn.__kwdefaults__
+ _inner.__kwdefaults__ = fn.__kwdefaults__ # type: ignore [attr-defined]
elif isinstance(fn, type) and hasattr(fn, "__init__"):
- _inner.__kwdefaults__ = fn.__init__.__kwdefaults__
+ _inner.__kwdefaults__ = fn.__init__.__kwdefaults__ # type: ignore [misc,attr-defined]
else:
- _inner.__kwdefaults__ = None
+ _inner.__kwdefaults__ = None # type: ignore [attr-defined]
_inner.__qualname__ = fn.__qualname__
return cast(C, _inner)
diff --git a/lib/pytz/__init__.py b/lib/pytz/__init__.py
index 2355f8b4..96409e2d 100644
--- a/lib/pytz/__init__.py
+++ b/lib/pytz/__init__.py
@@ -22,8 +22,8 @@ from pytz.tzfile import build_tzinfo
# The IANA (nee Olson) database is updated several times a year.
-OLSON_VERSION = '2024a'
-VERSION = '2024.1' # pip compatible version number.
+OLSON_VERSION = '2024b'
+VERSION = '2024.2' # pip compatible version number.
__version__ = VERSION
OLSEN_VERSION = OLSON_VERSION # Old releases had this misspelling
@@ -1340,7 +1340,6 @@ common_timezones = \
'Asia/Bishkek',
'Asia/Brunei',
'Asia/Chita',
- 'Asia/Choibalsan',
'Asia/Colombo',
'Asia/Damascus',
'Asia/Dhaka',
diff --git a/lib/pytz/zoneinfo/Africa/Blantyre b/lib/pytz/zoneinfo/Africa/Blantyre
index 52753c0f..65f043f1 100644
Binary files a/lib/pytz/zoneinfo/Africa/Blantyre and b/lib/pytz/zoneinfo/Africa/Blantyre differ
diff --git a/lib/pytz/zoneinfo/Africa/Bujumbura b/lib/pytz/zoneinfo/Africa/Bujumbura
index 52753c0f..65f043f1 100644
Binary files a/lib/pytz/zoneinfo/Africa/Bujumbura and b/lib/pytz/zoneinfo/Africa/Bujumbura differ
diff --git a/lib/pytz/zoneinfo/Africa/Gaborone b/lib/pytz/zoneinfo/Africa/Gaborone
index 52753c0f..65f043f1 100644
Binary files a/lib/pytz/zoneinfo/Africa/Gaborone and b/lib/pytz/zoneinfo/Africa/Gaborone differ
diff --git a/lib/pytz/zoneinfo/Africa/Harare b/lib/pytz/zoneinfo/Africa/Harare
index 52753c0f..65f043f1 100644
Binary files a/lib/pytz/zoneinfo/Africa/Harare and b/lib/pytz/zoneinfo/Africa/Harare differ
diff --git a/lib/pytz/zoneinfo/Africa/Kigali b/lib/pytz/zoneinfo/Africa/Kigali
index 52753c0f..65f043f1 100644
Binary files a/lib/pytz/zoneinfo/Africa/Kigali and b/lib/pytz/zoneinfo/Africa/Kigali differ
diff --git a/lib/pytz/zoneinfo/Africa/Lubumbashi b/lib/pytz/zoneinfo/Africa/Lubumbashi
index 52753c0f..65f043f1 100644
Binary files a/lib/pytz/zoneinfo/Africa/Lubumbashi and b/lib/pytz/zoneinfo/Africa/Lubumbashi differ
diff --git a/lib/pytz/zoneinfo/Africa/Lusaka b/lib/pytz/zoneinfo/Africa/Lusaka
index 52753c0f..65f043f1 100644
Binary files a/lib/pytz/zoneinfo/Africa/Lusaka and b/lib/pytz/zoneinfo/Africa/Lusaka differ
diff --git a/lib/pytz/zoneinfo/Africa/Maputo b/lib/pytz/zoneinfo/Africa/Maputo
index 52753c0f..65f043f1 100644
Binary files a/lib/pytz/zoneinfo/Africa/Maputo and b/lib/pytz/zoneinfo/Africa/Maputo differ
diff --git a/lib/pytz/zoneinfo/America/Bahia_Banderas b/lib/pytz/zoneinfo/America/Bahia_Banderas
index ae4a8a75..3a493e3d 100644
Binary files a/lib/pytz/zoneinfo/America/Bahia_Banderas and b/lib/pytz/zoneinfo/America/Bahia_Banderas differ
diff --git a/lib/pytz/zoneinfo/America/Cancun b/lib/pytz/zoneinfo/America/Cancun
index e7acbff1..0f7771e8 100644
Binary files a/lib/pytz/zoneinfo/America/Cancun and b/lib/pytz/zoneinfo/America/Cancun differ
diff --git a/lib/pytz/zoneinfo/America/Chihuahua b/lib/pytz/zoneinfo/America/Chihuahua
index e0910396..667a2191 100644
Binary files a/lib/pytz/zoneinfo/America/Chihuahua and b/lib/pytz/zoneinfo/America/Chihuahua differ
diff --git a/lib/pytz/zoneinfo/America/Ciudad_Juarez b/lib/pytz/zoneinfo/America/Ciudad_Juarez
index eb1e5396..29af5982 100644
Binary files a/lib/pytz/zoneinfo/America/Ciudad_Juarez and b/lib/pytz/zoneinfo/America/Ciudad_Juarez differ
diff --git a/lib/pytz/zoneinfo/America/Ensenada b/lib/pytz/zoneinfo/America/Ensenada
index 63dfdf48..0fe73912 100644
Binary files a/lib/pytz/zoneinfo/America/Ensenada and b/lib/pytz/zoneinfo/America/Ensenada differ
diff --git a/lib/pytz/zoneinfo/America/Hermosillo b/lib/pytz/zoneinfo/America/Hermosillo
index 86bd1a20..441fe3f2 100644
Binary files a/lib/pytz/zoneinfo/America/Hermosillo and b/lib/pytz/zoneinfo/America/Hermosillo differ
diff --git a/lib/pytz/zoneinfo/America/Mazatlan b/lib/pytz/zoneinfo/America/Mazatlan
index 06fa2274..386616a5 100644
Binary files a/lib/pytz/zoneinfo/America/Mazatlan and b/lib/pytz/zoneinfo/America/Mazatlan differ
diff --git a/lib/pytz/zoneinfo/America/Merida b/lib/pytz/zoneinfo/America/Merida
index 17654cb5..c4b9b4e8 100644
Binary files a/lib/pytz/zoneinfo/America/Merida and b/lib/pytz/zoneinfo/America/Merida differ
diff --git a/lib/pytz/zoneinfo/America/Mexico_City b/lib/pytz/zoneinfo/America/Mexico_City
index 68176daa..ad70cf3e 100644
Binary files a/lib/pytz/zoneinfo/America/Mexico_City and b/lib/pytz/zoneinfo/America/Mexico_City differ
diff --git a/lib/pytz/zoneinfo/America/Monterrey b/lib/pytz/zoneinfo/America/Monterrey
index 5eb723c8..2d7993a0 100644
Binary files a/lib/pytz/zoneinfo/America/Monterrey and b/lib/pytz/zoneinfo/America/Monterrey differ
diff --git a/lib/pytz/zoneinfo/America/Ojinaga b/lib/pytz/zoneinfo/America/Ojinaga
index f97946d1..45118a4f 100644
Binary files a/lib/pytz/zoneinfo/America/Ojinaga and b/lib/pytz/zoneinfo/America/Ojinaga differ
diff --git a/lib/pytz/zoneinfo/America/Santa_Isabel b/lib/pytz/zoneinfo/America/Santa_Isabel
index 63dfdf48..0fe73912 100644
Binary files a/lib/pytz/zoneinfo/America/Santa_Isabel and b/lib/pytz/zoneinfo/America/Santa_Isabel differ
diff --git a/lib/pytz/zoneinfo/America/Tijuana b/lib/pytz/zoneinfo/America/Tijuana
index 63dfdf48..0fe73912 100644
Binary files a/lib/pytz/zoneinfo/America/Tijuana and b/lib/pytz/zoneinfo/America/Tijuana differ
diff --git a/lib/pytz/zoneinfo/Asia/Choibalsan b/lib/pytz/zoneinfo/Asia/Choibalsan
index c5f4bb0b..2aa5cc4b 100644
Binary files a/lib/pytz/zoneinfo/Asia/Choibalsan and b/lib/pytz/zoneinfo/Asia/Choibalsan differ
diff --git a/lib/pytz/zoneinfo/Asia/Dili b/lib/pytz/zoneinfo/Asia/Dili
index c1af113a..4614e4fc 100644
Binary files a/lib/pytz/zoneinfo/Asia/Dili and b/lib/pytz/zoneinfo/Asia/Dili differ
diff --git a/lib/pytz/zoneinfo/Atlantic/Azores b/lib/pytz/zoneinfo/Atlantic/Azores
index 10232ab3..dd2c235b 100644
Binary files a/lib/pytz/zoneinfo/Atlantic/Azores and b/lib/pytz/zoneinfo/Atlantic/Azores differ
diff --git a/lib/pytz/zoneinfo/Atlantic/Madeira b/lib/pytz/zoneinfo/Atlantic/Madeira
index 7ddcd883..6725a0ff 100644
Binary files a/lib/pytz/zoneinfo/Atlantic/Madeira and b/lib/pytz/zoneinfo/Atlantic/Madeira differ
diff --git a/lib/pytz/zoneinfo/CET b/lib/pytz/zoneinfo/CET
index 122e9342..40d7124e 100644
Binary files a/lib/pytz/zoneinfo/CET and b/lib/pytz/zoneinfo/CET differ
diff --git a/lib/pytz/zoneinfo/CST6CDT b/lib/pytz/zoneinfo/CST6CDT
index ca67929f..c6981a06 100644
Binary files a/lib/pytz/zoneinfo/CST6CDT and b/lib/pytz/zoneinfo/CST6CDT differ
diff --git a/lib/pytz/zoneinfo/EET b/lib/pytz/zoneinfo/EET
index cbdb71dd..9f3a0678 100644
Binary files a/lib/pytz/zoneinfo/EET and b/lib/pytz/zoneinfo/EET differ
diff --git a/lib/pytz/zoneinfo/EST b/lib/pytz/zoneinfo/EST
index 21ebc00b..9964b9a3 100644
Binary files a/lib/pytz/zoneinfo/EST and b/lib/pytz/zoneinfo/EST differ
diff --git a/lib/pytz/zoneinfo/EST5EDT b/lib/pytz/zoneinfo/EST5EDT
index 9bce5007..a8b9ab19 100644
Binary files a/lib/pytz/zoneinfo/EST5EDT and b/lib/pytz/zoneinfo/EST5EDT differ
diff --git a/lib/pytz/zoneinfo/Europe/Lisbon b/lib/pytz/zoneinfo/Europe/Lisbon
index 55f01930..616de167 100644
Binary files a/lib/pytz/zoneinfo/Europe/Lisbon and b/lib/pytz/zoneinfo/Europe/Lisbon differ
diff --git a/lib/pytz/zoneinfo/HST b/lib/pytz/zoneinfo/HST
index cccd45eb..c7cd0601 100644
Binary files a/lib/pytz/zoneinfo/HST and b/lib/pytz/zoneinfo/HST differ
diff --git a/lib/pytz/zoneinfo/MET b/lib/pytz/zoneinfo/MET
index 4a826bb1..40d7124e 100644
Binary files a/lib/pytz/zoneinfo/MET and b/lib/pytz/zoneinfo/MET differ
diff --git a/lib/pytz/zoneinfo/MST b/lib/pytz/zoneinfo/MST
index c93a58ee..ab37e845 100644
Binary files a/lib/pytz/zoneinfo/MST and b/lib/pytz/zoneinfo/MST differ
diff --git a/lib/pytz/zoneinfo/MST7MDT b/lib/pytz/zoneinfo/MST7MDT
index 4506a6e1..abb2b974 100644
Binary files a/lib/pytz/zoneinfo/MST7MDT and b/lib/pytz/zoneinfo/MST7MDT differ
diff --git a/lib/pytz/zoneinfo/Mexico/BajaNorte b/lib/pytz/zoneinfo/Mexico/BajaNorte
index 63dfdf48..0fe73912 100644
Binary files a/lib/pytz/zoneinfo/Mexico/BajaNorte and b/lib/pytz/zoneinfo/Mexico/BajaNorte differ
diff --git a/lib/pytz/zoneinfo/Mexico/BajaSur b/lib/pytz/zoneinfo/Mexico/BajaSur
index 06fa2274..386616a5 100644
Binary files a/lib/pytz/zoneinfo/Mexico/BajaSur and b/lib/pytz/zoneinfo/Mexico/BajaSur differ
diff --git a/lib/pytz/zoneinfo/Mexico/General b/lib/pytz/zoneinfo/Mexico/General
index 68176daa..ad70cf3e 100644
Binary files a/lib/pytz/zoneinfo/Mexico/General and b/lib/pytz/zoneinfo/Mexico/General differ
diff --git a/lib/pytz/zoneinfo/PST8PDT b/lib/pytz/zoneinfo/PST8PDT
index 99d246ba..610e7af5 100644
Binary files a/lib/pytz/zoneinfo/PST8PDT and b/lib/pytz/zoneinfo/PST8PDT differ
diff --git a/lib/pytz/zoneinfo/Portugal b/lib/pytz/zoneinfo/Portugal
index 55f01930..616de167 100644
Binary files a/lib/pytz/zoneinfo/Portugal and b/lib/pytz/zoneinfo/Portugal differ
diff --git a/lib/pytz/zoneinfo/WET b/lib/pytz/zoneinfo/WET
index c27390b5..616de167 100644
Binary files a/lib/pytz/zoneinfo/WET and b/lib/pytz/zoneinfo/WET differ
diff --git a/lib/pytz/zoneinfo/leapseconds b/lib/pytz/zoneinfo/leapseconds
index ce150bfe..6c715cb2 100644
--- a/lib/pytz/zoneinfo/leapseconds
+++ b/lib/pytz/zoneinfo/leapseconds
@@ -69,11 +69,11 @@ Leap 2016 Dec 31 23:59:60 + S
# Any additional leap seconds will come after this.
# This Expires line is commented out for now,
# so that pre-2020a zic implementations do not reject this file.
-#Expires 2024 Dec 28 00:00:00
+#Expires 2025 Jun 28 00:00:00
# POSIX timestamps for the data in this file:
-#updated 1704708379 (2024-01-08 10:06:19 UTC)
-#expires 1735344000 (2024-12-28 00:00:00 UTC)
+#updated 1720104763 (2024-07-04 14:52:43 UTC)
+#expires 1751068800 (2025-06-28 00:00:00 UTC)
# Updated through IERS Bulletin C (https://hpiers.obspm.fr/iers/bul/bulc/bulletinc.dat)
-# File expires on 28 December 2024
+# File expires on 28 June 2025
diff --git a/lib/pytz/zoneinfo/tzdata.zi b/lib/pytz/zoneinfo/tzdata.zi
index b5a03be7..b89326a7 100644
--- a/lib/pytz/zoneinfo/tzdata.zi
+++ b/lib/pytz/zoneinfo/tzdata.zi
@@ -1324,14 +1324,10 @@ R O 1961 1964 - May lastSu 1s 1 S
R O 1962 1964 - S lastSu 1s 0 -
R p 1916 o - Jun 17 23 1 S
R p 1916 o - N 1 1 0 -
-R p 1917 o - F 28 23s 1 S
-R p 1917 1921 - O 14 23s 0 -
-R p 1918 o - Mar 1 23s 1 S
-R p 1919 o - F 28 23s 1 S
-R p 1920 o - F 29 23s 1 S
-R p 1921 o - F 28 23s 1 S
+R p 1917 1921 - Mar 1 0 1 S
+R p 1917 1921 - O 14 24 0 -
R p 1924 o - Ap 16 23s 1 S
-R p 1924 o - O 14 23s 0 -
+R p 1924 o - O 4 23s 0 -
R p 1926 o - Ap 17 23s 1 S
R p 1926 1929 - O Sa>=1 23s 0 -
R p 1927 o - Ap 9 23s 1 S
@@ -1349,8 +1345,9 @@ R p 1938 o - Mar 26 23s 1 S
R p 1939 o - Ap 15 23s 1 S
R p 1939 o - N 18 23s 0 -
R p 1940 o - F 24 23s 1 S
-R p 1940 1941 - O 5 23s 0 -
+R p 1940 o - O 7 23s 0 -
R p 1941 o - Ap 5 23s 1 S
+R p 1941 o - O 5 23s 0 -
R p 1942 1945 - Mar Sa>=8 23s 1 S
R p 1942 o - Ap 25 22s 2 M
R p 1942 o - Au 15 22s 1 S
@@ -1360,16 +1357,16 @@ R p 1943 1945 - Au Sa>=25 22s 1 S
R p 1944 1945 - Ap Sa>=21 22s 2 M
R p 1946 o - Ap Sa>=1 23s 1 S
R p 1946 o - O Sa>=1 23s 0 -
-R p 1947 1965 - Ap Su>=1 2s 1 S
+R p 1947 1966 - Ap Su>=1 2s 1 S
R p 1947 1965 - O Su>=1 2s 0 -
-R p 1977 o - Mar 27 0s 1 S
-R p 1977 o - S 25 0s 0 -
-R p 1978 1979 - Ap Su>=1 0s 1 S
-R p 1978 o - O 1 0s 0 -
-R p 1979 1982 - S lastSu 1s 0 -
-R p 1980 o - Mar lastSu 0s 1 S
-R p 1981 1982 - Mar lastSu 1s 1 S
-R p 1983 o - Mar lastSu 2s 1 S
+R p 1976 o - S lastSu 1 0 -
+R p 1977 o - Mar lastSu 0s 1 S
+R p 1977 o - S lastSu 0s 0 -
+R p 1978 1980 - Ap Su>=1 1s 1 S
+R p 1978 o - O 1 1s 0 -
+R p 1979 1980 - S lastSu 1s 0 -
+R p 1981 1986 - Mar lastSu 0s 1 S
+R p 1981 1985 - S lastSu 0s 0 -
R z 1932 o - May 21 0s 1 S
R z 1932 1939 - O Su>=1 0s 0 -
R z 1933 1939 - Ap Su>=2 0s 1 S
@@ -1728,7 +1725,7 @@ R Y 1972 2006 - O lastSu 2 0 S
R Y 1987 2006 - Ap Su>=1 2 1 D
R Yu 1965 o - Ap lastSu 0 2 DD
R Yu 1965 o - O lastSu 2 0 S
-R m 1931 o - May 1 23 1 D
+R m 1931 o - April 30 0 1 D
R m 1931 o - O 1 0 0 S
R m 1939 o - F 5 0 1 D
R m 1939 o - Jun 25 0 0 S
@@ -2096,15 +2093,15 @@ Z Africa/Algiers 0:12:12 - LMT 1891 Mar 16
0 d WE%sT 1981 May
1 - CET
Z Africa/Bissau -1:2:20 - LMT 1912 Ja 1 1u
--1 - -01 1975
+-1 - %z 1975
0 - GMT
Z Africa/Cairo 2:5:9 - LMT 1900 O
2 K EE%sT
Z Africa/Casablanca -0:30:20 - LMT 1913 O 26
-0 M +00/+01 1984 Mar 16
-1 - +01 1986
-0 M +00/+01 2018 O 28 3
-1 M +01/+00
+0 M %z 1984 Mar 16
+1 - %z 1986
+0 M %z 2018 O 28 3
+1 M %z
Z Africa/Ceuta -0:21:16 - LMT 1901 Ja 1 0u
0 - WET 1918 May 6 23
0 1 WEST 1918 O 7 23
@@ -2115,9 +2112,9 @@ Z Africa/Ceuta -0:21:16 - LMT 1901 Ja 1 0u
1 - CET 1986
1 E CE%sT
Z Africa/El_Aaiun -0:52:48 - LMT 1934
--1 - -01 1976 Ap 14
-0 M +00/+01 2018 O 28 3
-1 M +01/+00
+-1 - %z 1976 Ap 14
+0 M %z 2018 O 28 3
+1 M %z
Z Africa/Johannesburg 1:52 - LMT 1892 F 8
1:30 - SAST 1903 Mar
2 SA SAST
@@ -2132,19 +2129,19 @@ Z Africa/Khartoum 2:10:8 - LMT 1931
Z Africa/Lagos 0:13:35 - LMT 1905 Jul
0 - GMT 1908 Jul
0:13:35 - LMT 1914
-0:30 - +0030 1919 S
+0:30 - %z 1919 S
1 - WAT
-Z Africa/Maputo 2:10:20 - LMT 1903 Mar
+Z Africa/Maputo 2:10:18 - LMT 1909
2 - CAT
Z Africa/Monrovia -0:43:8 - LMT 1882
-0:43:8 - MMT 1919 Mar
-0:44:30 - MMT 1972 Ja 7
0 - GMT
Z Africa/Nairobi 2:27:16 - LMT 1908 May
-2:30 - +0230 1928 Jun 30 24
+2:30 - %z 1928 Jun 30 24
3 - EAT 1930 Ja 4 24
-2:30 - +0230 1936 D 31 24
-2:45 - +0245 1942 Jul 31 24
+2:30 - %z 1936 D 31 24
+2:45 - %z 1942 Jul 31 24
3 - EAT
Z Africa/Ndjamena 1:0:12 - LMT 1912
1 - WAT 1979 O 14
@@ -2168,7 +2165,7 @@ Z Africa/Tunis 0:40:44 - LMT 1881 May 12
0:9:21 - PMT 1911 Mar 11
1 n CE%sT
Z Africa/Windhoek 1:8:24 - LMT 1892 F 8
-1:30 - +0130 1903 Mar
+1:30 - %z 1903 Mar
2 - SAST 1942 S 20 2
2 1 SAST 1943 Mar 21 2
2 - SAST 1990 Mar 21
@@ -2191,167 +2188,166 @@ Z America/Anchorage 14:0:24 - LMT 1867 O 19 14:31:37
-9 u Y%sT 1983 N 30
-9 u AK%sT
Z America/Araguaina -3:12:48 - LMT 1914
--3 B -03/-02 1990 S 17
--3 - -03 1995 S 14
--3 B -03/-02 2003 S 24
--3 - -03 2012 O 21
--3 B -03/-02 2013 S
--3 - -03
+-3 B %z 1990 S 17
+-3 - %z 1995 S 14
+-3 B %z 2003 S 24
+-3 - %z 2012 O 21
+-3 B %z 2013 S
+-3 - %z
Z America/Argentina/Buenos_Aires -3:53:48 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 A -03/-02
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 A %z
Z America/Argentina/Catamarca -4:23:8 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1991 Mar 3
--4 - -04 1991 O 20
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 - -03 2004 Jun
--4 - -04 2004 Jun 20
--3 A -03/-02 2008 O 18
--3 - -03
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1991 Mar 3
+-4 - %z 1991 O 20
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 Jun
+-4 - %z 2004 Jun 20
+-3 A %z 2008 O 18
+-3 - %z
Z America/Argentina/Cordoba -4:16:48 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1991 Mar 3
--4 - -04 1991 O 20
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 A -03/-02
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1991 Mar 3
+-4 - %z 1991 O 20
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 A %z
Z America/Argentina/Jujuy -4:21:12 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1990 Mar 4
--4 - -04 1990 O 28
--4 1 -03 1991 Mar 17
--4 - -04 1991 O 6
--3 1 -02 1992
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 A -03/-02 2008 O 18
--3 - -03
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1990 Mar 4
+-4 - %z 1990 O 28
+-4 1 %z 1991 Mar 17
+-4 - %z 1991 O 6
+-3 1 %z 1992
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 A %z 2008 O 18
+-3 - %z
Z America/Argentina/La_Rioja -4:27:24 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1991 Mar
--4 - -04 1991 May 7
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 - -03 2004 Jun
--4 - -04 2004 Jun 20
--3 A -03/-02 2008 O 18
--3 - -03
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1991 Mar
+-4 - %z 1991 May 7
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 Jun
+-4 - %z 2004 Jun 20
+-3 A %z 2008 O 18
+-3 - %z
Z America/Argentina/Mendoza -4:35:16 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1990 Mar 4
--4 - -04 1990 O 15
--4 1 -03 1991 Mar
--4 - -04 1991 O 15
--4 1 -03 1992 Mar
--4 - -04 1992 O 18
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 - -03 2004 May 23
--4 - -04 2004 S 26
--3 A -03/-02 2008 O 18
--3 - -03
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1990 Mar 4
+-4 - %z 1990 O 15
+-4 1 %z 1991 Mar
+-4 - %z 1991 O 15
+-4 1 %z 1992 Mar
+-4 - %z 1992 O 18
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 May 23
+-4 - %z 2004 S 26
+-3 A %z 2008 O 18
+-3 - %z
Z America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 - -03 2004 Jun
--4 - -04 2004 Jun 20
--3 A -03/-02 2008 O 18
--3 - -03
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 Jun
+-4 - %z 2004 Jun 20
+-3 A %z 2008 O 18
+-3 - %z
Z America/Argentina/Salta -4:21:40 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1991 Mar 3
--4 - -04 1991 O 20
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 A -03/-02 2008 O 18
--3 - -03
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1991 Mar 3
+-4 - %z 1991 O 20
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 A %z 2008 O 18
+-3 - %z
Z America/Argentina/San_Juan -4:34:4 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1991 Mar
--4 - -04 1991 May 7
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 - -03 2004 May 31
--4 - -04 2004 Jul 25
--3 A -03/-02 2008 O 18
--3 - -03
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1991 Mar
+-4 - %z 1991 May 7
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 May 31
+-4 - %z 2004 Jul 25
+-3 A %z 2008 O 18
+-3 - %z
Z America/Argentina/San_Luis -4:25:24 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1990
--3 1 -02 1990 Mar 14
--4 - -04 1990 O 15
--4 1 -03 1991 Mar
--4 - -04 1991 Jun
--3 - -03 1999 O 3
--4 1 -03 2000 Mar 3
--3 - -03 2004 May 31
--4 - -04 2004 Jul 25
--3 A -03/-02 2008 Ja 21
--4 Sa -04/-03 2009 O 11
--3 - -03
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1990
+-3 1 %z 1990 Mar 14
+-4 - %z 1990 O 15
+-4 1 %z 1991 Mar
+-4 - %z 1991 Jun
+-3 - %z 1999 O 3
+-4 1 %z 2000 Mar 3
+-3 - %z 2004 May 31
+-4 - %z 2004 Jul 25
+-3 A %z 2008 Ja 21
+-4 Sa %z 2009 O 11
+-3 - %z
Z America/Argentina/Tucuman -4:20:52 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1991 Mar 3
--4 - -04 1991 O 20
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 - -03 2004 Jun
--4 - -04 2004 Jun 13
--3 A -03/-02
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1991 Mar 3
+-4 - %z 1991 O 20
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 Jun
+-4 - %z 2004 Jun 13
+-3 A %z
Z America/Argentina/Ushuaia -4:33:12 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 - -03 2004 May 30
--4 - -04 2004 Jun 20
--3 A -03/-02 2008 O 18
--3 - -03
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 May 30
+-4 - %z 2004 Jun 20
+-3 A %z 2008 O 18
+-3 - %z
Z America/Asuncion -3:50:40 - LMT 1890
-3:50:40 - AMT 1931 O 10
--4 - -04 1972 O
--3 - -03 1974 Ap
--4 y -04/-03
+-4 - %z 1972 O
+-3 - %z 1974 Ap
+-4 y %z
Z America/Bahia -2:34:4 - LMT 1914
--3 B -03/-02 2003 S 24
--3 - -03 2011 O 16
--3 B -03/-02 2012 O 21
--3 - -03
+-3 B %z 2003 S 24
+-3 - %z 2011 O 16
+-3 B %z 2012 O 21
+-3 - %z
Z America/Bahia_Banderas -7:1 - LMT 1922 Ja 1 7u
--7 - MST 1927 Jun 10 23
+-7 - MST 1927 Jun 10
-6 - CST 1930 N 15
-7 m M%sT 1932 Ap
-6 - CST 1942 Ap 24
--7 - MST 1949 Ja 14
--8 - PST 1970
+-7 - MST 1970
-7 m M%sT 2010 Ap 4 2
-6 m C%sT
Z America/Barbados -3:58:29 - LMT 1911 Au 28
@@ -2359,18 +2355,18 @@ Z America/Barbados -3:58:29 - LMT 1911 Au 28
-4 BB AST/-0330 1945
-4 BB A%sT
Z America/Belem -3:13:56 - LMT 1914
--3 B -03/-02 1988 S 12
--3 - -03
+-3 B %z 1988 S 12
+-3 - %z
Z America/Belize -5:52:48 - LMT 1912 Ap
-6 BZ %s
Z America/Boa_Vista -4:2:40 - LMT 1914
--4 B -04/-03 1988 S 12
--4 - -04 1999 S 30
--4 B -04/-03 2000 O 15
--4 - -04
+-4 B %z 1988 S 12
+-4 - %z 1999 S 30
+-4 B %z 2000 O 15
+-4 - %z
Z America/Bogota -4:56:16 - LMT 1884 Mar 13
-4:56:16 - BMT 1914 N 23
--5 CO -05/-04
+-5 CO %z
Z America/Boise -7:44:49 - LMT 1883 N 18 20u
-8 u P%sT 1923 May 13 2
-7 u M%sT 1974
@@ -2383,21 +2379,23 @@ Z America/Cambridge_Bay 0 - -00 1920
-6 - CST 2001 Ap 1 3
-7 C M%sT
Z America/Campo_Grande -3:38:28 - LMT 1914
--4 B -04/-03
+-4 B %z
Z America/Cancun -5:47:4 - LMT 1922 Ja 1 6u
--6 - CST 1981 D 23
+-6 - CST 1981 D 26 2
+-5 - EST 1983 Ja 4
+-6 m C%sT 1997 O 26 2
-5 m E%sT 1998 Au 2 2
-6 m C%sT 2015 F 1 2
-5 - EST
Z America/Caracas -4:27:44 - LMT 1890
-4:27:40 - CMT 1912 F 12
--4:30 - -0430 1965
--4 - -04 2007 D 9 3
--4:30 - -0430 2016 May 1 2:30
--4 - -04
+-4:30 - %z 1965
+-4 - %z 2007 D 9 3
+-4:30 - %z 2016 May 1 2:30
+-4 - %z
Z America/Cayenne -3:29:20 - LMT 1911 Jul
--4 - -04 1967 O
--3 - -03
+-4 - %z 1967 O
+-3 - %z
Z America/Chicago -5:50:36 - LMT 1883 N 18 18u
-6 u C%sT 1920
-6 Ch C%sT 1936 Mar 1 2
@@ -2407,7 +2405,7 @@ Z America/Chicago -5:50:36 - LMT 1883 N 18 18u
-6 Ch C%sT 1967
-6 u C%sT
Z America/Chihuahua -7:4:20 - LMT 1922 Ja 1 7u
--7 - MST 1927 Jun 10 23
+-7 - MST 1927 Jun 10
-6 - CST 1930 N 15
-7 m M%sT 1932 Ap
-6 - CST 1996
@@ -2416,7 +2414,7 @@ Z America/Chihuahua -7:4:20 - LMT 1922 Ja 1 7u
-7 m M%sT 2022 O 30 2
-6 - CST
Z America/Ciudad_Juarez -7:5:56 - LMT 1922 Ja 1 7u
--7 - MST 1927 Jun 10 23
+-7 - MST 1927 Jun 10
-6 - CST 1930 N 15
-7 m M%sT 1932 Ap
-6 - CST 1996
@@ -2430,12 +2428,12 @@ Z America/Costa_Rica -5:36:13 - LMT 1890
-5:36:13 - SJMT 1921 Ja 15
-6 CR C%sT
Z America/Cuiaba -3:44:20 - LMT 1914
--4 B -04/-03 2003 S 24
--4 - -04 2004 O
--4 B -04/-03
+-4 B %z 2003 S 24
+-4 - %z 2004 O
+-4 B %z
Z America/Danmarkshavn -1:14:40 - LMT 1916 Jul 28
--3 - -03 1980 Ap 6 2
--3 E -03/-02 1996
+-3 - %z 1980 Ap 6 2
+-3 E %z 1996
0 - GMT
Z America/Dawson -9:17:40 - LMT 1900 Au 20
-9 Y Y%sT 1965
@@ -2467,12 +2465,12 @@ Z America/Edmonton -7:33:52 - LMT 1906 S
-7 Ed M%sT 1987
-7 C M%sT
Z America/Eirunepe -4:39:28 - LMT 1914
--5 B -05/-04 1988 S 12
--5 - -05 1993 S 28
--5 B -05/-04 1994 S 22
--5 - -05 2008 Jun 24
--4 - -04 2013 N 10
--5 - -05
+-5 B %z 1988 S 12
+-5 - %z 1993 S 28
+-5 B %z 1994 S 22
+-5 - %z 2008 Jun 24
+-4 - %z 2013 N 10
+-5 - %z
Z America/El_Salvador -5:56:48 - LMT 1921
-6 SV C%sT
Z America/Fort_Nelson -8:10:47 - LMT 1884
@@ -2482,12 +2480,12 @@ Z America/Fort_Nelson -8:10:47 - LMT 1884
-8 C P%sT 2015 Mar 8 2
-7 - MST
Z America/Fortaleza -2:34 - LMT 1914
--3 B -03/-02 1990 S 17
--3 - -03 1999 S 30
--3 B -03/-02 2000 O 22
--3 - -03 2001 S 13
--3 B -03/-02 2002 O
--3 - -03
+-3 B %z 1990 S 17
+-3 - %z 1999 S 30
+-3 B %z 2000 O 22
+-3 - %z 2001 S 13
+-3 B %z 2002 O
+-3 - %z
Z America/Glace_Bay -3:59:48 - LMT 1902 Jun 15
-4 C A%sT 1953
-4 H A%sT 1954
@@ -2514,12 +2512,12 @@ Z America/Guatemala -6:2:4 - LMT 1918 O 5
-6 GT C%sT
Z America/Guayaquil -5:19:20 - LMT 1890
-5:14 - QMT 1931
--5 EC -05/-04
+-5 EC %z
Z America/Guyana -3:52:39 - LMT 1911 Au
--4 - -04 1915 Mar
--3:45 - -0345 1975 Au
--3 - -03 1992 Mar 29 1
--4 - -04
+-4 - %z 1915 Mar
+-3:45 - %z 1975 Au
+-3 - %z 1992 Mar 29 1
+-4 - %z
Z America/Halifax -4:14:24 - LMT 1902 Jun 15
-4 H A%sT 1918
-4 C A%sT 1919
@@ -2531,12 +2529,11 @@ Z America/Havana -5:29:28 - LMT 1890
-5:29:36 - HMT 1925 Jul 19 12
-5 Q C%sT
Z America/Hermosillo -7:23:52 - LMT 1922 Ja 1 7u
--7 - MST 1927 Jun 10 23
+-7 - MST 1927 Jun 10
-6 - CST 1930 N 15
-7 m M%sT 1932 Ap
-6 - CST 1942 Ap 24
--7 - MST 1949 Ja 14
--8 - PST 1970
+-7 - MST 1996
-7 m M%sT 1999
-7 - MST
Z America/Indiana/Indianapolis -5:44:38 - LMT 1883 N 18 18u
@@ -2644,23 +2641,23 @@ Z America/Kentucky/Monticello -5:39:24 - LMT 1883 N 18 18u
Z America/La_Paz -4:32:36 - LMT 1890
-4:32:36 - CMT 1931 O 15
-4:32:36 1 BST 1932 Mar 21
--4 - -04
+-4 - %z
Z America/Lima -5:8:12 - LMT 1890
-5:8:36 - LMT 1908 Jul 28
--5 PE -05/-04
+-5 PE %z
Z America/Los_Angeles -7:52:58 - LMT 1883 N 18 20u
-8 u P%sT 1946
-8 CA P%sT 1967
-8 u P%sT
Z America/Maceio -2:22:52 - LMT 1914
--3 B -03/-02 1990 S 17
--3 - -03 1995 O 13
--3 B -03/-02 1996 S 4
--3 - -03 1999 S 30
--3 B -03/-02 2000 O 22
--3 - -03 2001 S 13
--3 B -03/-02 2002 O
--3 - -03
+-3 B %z 1990 S 17
+-3 - %z 1995 O 13
+-3 B %z 1996 S 4
+-3 - %z 1999 S 30
+-3 B %z 2000 O 22
+-3 - %z 2001 S 13
+-3 B %z 2002 O
+-3 - %z
Z America/Managua -5:45:8 - LMT 1890
-5:45:12 - MMT 1934 Jun 23
-6 - CST 1973 May
@@ -2671,10 +2668,10 @@ Z America/Managua -5:45:8 - LMT 1890
-5 - EST 1997
-6 NI C%sT
Z America/Manaus -4:0:4 - LMT 1914
--4 B -04/-03 1988 S 12
--4 - -04 1993 S 28
--4 B -04/-03 1994 S 22
--4 - -04
+-4 B %z 1988 S 12
+-4 - %z 1993 S 28
+-4 B %z 1994 S 22
+-4 - %z
Z America/Martinique -4:4:20 - LMT 1890
-4:4:20 - FFMT 1911 May
-4 - AST 1980 Ap 6
@@ -2686,12 +2683,11 @@ Z America/Matamoros -6:30 - LMT 1922 Ja 1 6u
-6 m C%sT 2010
-6 u C%sT
Z America/Mazatlan -7:5:40 - LMT 1922 Ja 1 7u
--7 - MST 1927 Jun 10 23
+-7 - MST 1927 Jun 10
-6 - CST 1930 N 15
-7 m M%sT 1932 Ap
-6 - CST 1942 Ap 24
--7 - MST 1949 Ja 14
--8 - PST 1970
+-7 - MST 1970
-7 m M%sT
Z America/Menominee -5:50:27 - LMT 1885 S 18 12
-6 u C%sT 1946
@@ -2699,8 +2695,8 @@ Z America/Menominee -5:50:27 - LMT 1885 S 18 12
-5 - EST 1973 Ap 29 2
-6 u C%sT
Z America/Merida -5:58:28 - LMT 1922 Ja 1 6u
--6 - CST 1981 D 23
--5 - EST 1982 D 2
+-6 - CST 1981 D 26 2
+-5 - EST 1982 N 2 2
-6 m C%sT
Z America/Metlakatla 15:13:42 - LMT 1867 O 19 15:44:55
-8:46:18 - LMT 1900 Au 20 12
@@ -2713,7 +2709,7 @@ Z America/Metlakatla 15:13:42 - LMT 1867 O 19 15:44:55
-8 - PST 2019 Ja 20 2
-9 u AK%sT
Z America/Mexico_City -6:36:36 - LMT 1922 Ja 1 7u
--7 - MST 1927 Jun 10 23
+-7 - MST 1927 Jun 10
-6 - CST 1930 N 15
-7 m M%sT 1932 Ap
-6 m C%sT 2001 S 30 2
@@ -2721,8 +2717,8 @@ Z America/Mexico_City -6:36:36 - LMT 1922 Ja 1 7u
-6 m C%sT
Z America/Miquelon -3:44:40 - LMT 1911 Jun 15
-4 - AST 1980 May
--3 - -03 1987
--3 C -03/-02
+-3 - %z 1987
+-3 C %z
Z America/Moncton -4:19:8 - LMT 1883 D 9
-5 - EST 1902 Jun 15
-4 C A%sT 1933
@@ -2733,20 +2729,23 @@ Z America/Moncton -4:19:8 - LMT 1883 D 9
-4 o A%sT 2007
-4 C A%sT
Z America/Monterrey -6:41:16 - LMT 1922 Ja 1 6u
+-7 - MST 1927 Jun 10
+-6 - CST 1930 N 15
+-7 m M%sT 1932 Ap
-6 - CST 1988
-6 u C%sT 1989
-6 m C%sT
Z America/Montevideo -3:44:51 - LMT 1908 Jun 10
-3:44:51 - MMT 1920 May
--4 - -04 1923 O
--3:30 U -0330/-03 1942 D 14
--3 U -03/-0230 1960
--3 U -03/-02 1968
--3 U -03/-0230 1970
--3 U -03/-02 1974
--3 U -03/-0130 1974 Mar 10
--3 U -03/-0230 1974 D 22
--3 U -03/-02
+-4 - %z 1923 O
+-3:30 U %z 1942 D 14
+-3 U %z 1960
+-3 U %z 1968
+-3 U %z 1970
+-3 U %z 1974
+-3 U %z 1974 Mar 10
+-3 U %z 1974 D 22
+-3 U %z
Z America/New_York -4:56:2 - LMT 1883 N 18 17u
-5 u E%sT 1920
-5 NY E%sT 1942
@@ -2763,12 +2762,12 @@ Z America/Nome 12:58:22 - LMT 1867 O 19 13:29:35
-9 u Y%sT 1983 N 30
-9 u AK%sT
Z America/Noronha -2:9:40 - LMT 1914
--2 B -02/-01 1990 S 17
--2 - -02 1999 S 30
--2 B -02/-01 2000 O 15
--2 - -02 2001 S 13
--2 B -02/-01 2002 O
--2 - -02
+-2 B %z 1990 S 17
+-2 - %z 1999 S 30
+-2 B %z 2000 O 15
+-2 - %z 2001 S 13
+-2 B %z 2002 O
+-2 - %z
Z America/North_Dakota/Beulah -6:47:7 - LMT 1883 N 18 19u
-7 u M%sT 2010 N 7 2
-6 u C%sT
@@ -2779,12 +2778,12 @@ Z America/North_Dakota/New_Salem -6:45:39 - LMT 1883 N 18 19u
-7 u M%sT 2003 O 26 2
-6 u C%sT
Z America/Nuuk -3:26:56 - LMT 1916 Jul 28
--3 - -03 1980 Ap 6 2
--3 E -03/-02 2023 Mar 26 1u
--2 - -02 2023 O 29 1u
--2 E -02/-01
+-3 - %z 1980 Ap 6 2
+-3 E %z 2023 Mar 26 1u
+-2 - %z 2023 O 29 1u
+-2 E %z
Z America/Ojinaga -6:57:40 - LMT 1922 Ja 1 7u
--7 - MST 1927 Jun 10 23
+-7 - MST 1927 Jun 10
-6 - CST 1930 N 15
-7 m M%sT 1932 Ap
-6 - CST 1996
@@ -2800,8 +2799,8 @@ Z America/Panama -5:18:8 - LMT 1890
Z America/Paramaribo -3:40:40 - LMT 1911
-3:40:52 - PMT 1935
-3:40:36 - PMT 1945 O
--3:30 - -0330 1984 O
--3 - -03
+-3:30 - %z 1984 O
+-3 - %z
Z America/Phoenix -7:28:18 - LMT 1883 N 18 19u
-7 u M%sT 1944 Ja 1 0:1
-7 - MST 1944 Ap 1 0:1
@@ -2813,37 +2812,37 @@ Z America/Port-au-Prince -4:49:20 - LMT 1890
-4:49 - PPMT 1917 Ja 24 12
-5 HT E%sT
Z America/Porto_Velho -4:15:36 - LMT 1914
--4 B -04/-03 1988 S 12
--4 - -04
+-4 B %z 1988 S 12
+-4 - %z
Z America/Puerto_Rico -4:24:25 - LMT 1899 Mar 28 12
-4 - AST 1942 May 3
-4 u A%sT 1946
-4 - AST
Z America/Punta_Arenas -4:43:40 - LMT 1890
-4:42:45 - SMT 1910 Ja 10
--5 - -05 1916 Jul
+-5 - %z 1916 Jul
-4:42:45 - SMT 1918 S 10
--4 - -04 1919 Jul
+-4 - %z 1919 Jul
-4:42:45 - SMT 1927 S
--5 x -05/-04 1932 S
--4 - -04 1942 Jun
--5 - -05 1942 Au
--4 - -04 1946 Au 28 24
--5 1 -04 1947 Mar 31 24
--5 - -05 1947 May 21 23
--4 x -04/-03 2016 D 4
--3 - -03
+-5 x %z 1932 S
+-4 - %z 1942 Jun
+-5 - %z 1942 Au
+-4 - %z 1946 Au 28 24
+-5 1 %z 1947 Mar 31 24
+-5 - %z 1947 May 21 23
+-4 x %z 2016 D 4
+-3 - %z
Z America/Rankin_Inlet 0 - -00 1957
-6 Y C%sT 2000 O 29 2
-5 - EST 2001 Ap 1 3
-6 C C%sT
Z America/Recife -2:19:36 - LMT 1914
--3 B -03/-02 1990 S 17
--3 - -03 1999 S 30
--3 B -03/-02 2000 O 15
--3 - -03 2001 S 13
--3 B -03/-02 2002 O
--3 - -03
+-3 B %z 1990 S 17
+-3 - %z 1999 S 30
+-3 B %z 2000 O 15
+-3 - %z 2001 S 13
+-3 B %z 2002 O
+-3 - %z
Z America/Regina -6:58:36 - LMT 1905 S
-7 r M%sT 1960 Ap lastSu 2
-6 - CST
@@ -2854,28 +2853,28 @@ Z America/Resolute 0 - -00 1947 Au 31
-5 - EST 2007 Mar 11 3
-6 C C%sT
Z America/Rio_Branco -4:31:12 - LMT 1914
--5 B -05/-04 1988 S 12
--5 - -05 2008 Jun 24
--4 - -04 2013 N 10
--5 - -05
+-5 B %z 1988 S 12
+-5 - %z 2008 Jun 24
+-4 - %z 2013 N 10
+-5 - %z
Z America/Santarem -3:38:48 - LMT 1914
--4 B -04/-03 1988 S 12
--4 - -04 2008 Jun 24
--3 - -03
+-4 B %z 1988 S 12
+-4 - %z 2008 Jun 24
+-3 - %z
Z America/Santiago -4:42:45 - LMT 1890
-4:42:45 - SMT 1910 Ja 10
--5 - -05 1916 Jul
+-5 - %z 1916 Jul
-4:42:45 - SMT 1918 S 10
--4 - -04 1919 Jul
+-4 - %z 1919 Jul
-4:42:45 - SMT 1927 S
--5 x -05/-04 1932 S
--4 - -04 1942 Jun
--5 - -05 1942 Au
--4 - -04 1946 Jul 14 24
--4 1 -03 1946 Au 28 24
--5 1 -04 1947 Mar 31 24
--5 - -05 1947 May 21 23
--4 x -04/-03
+-5 x %z 1932 S
+-4 - %z 1942 Jun
+-5 - %z 1942 Au
+-4 - %z 1946 Jul 14 24
+-4 1 %z 1946 Au 28 24
+-5 1 %z 1947 Mar 31 24
+-5 - %z 1947 May 21 23
+-4 x %z
Z America/Santo_Domingo -4:39:36 - LMT 1890
-4:40 - SDMT 1933 Ap 1 12
-5 DO %s 1974 O 27
@@ -2883,14 +2882,14 @@ Z America/Santo_Domingo -4:39:36 - LMT 1890
-5 u E%sT 2000 D 3 1
-4 - AST
Z America/Sao_Paulo -3:6:28 - LMT 1914
--3 B -03/-02 1963 O 23
--3 1 -02 1964
--3 B -03/-02
+-3 B %z 1963 O 23
+-3 1 %z 1964
+-3 B %z
Z America/Scoresbysund -1:27:52 - LMT 1916 Jul 28
--2 - -02 1980 Ap 6 2
--2 c -02/-01 1981 Mar 29
--1 E -01/+00 2024 Mar 31
--2 E -02/-01
+-2 - %z 1980 Ap 6 2
+-2 c %z 1981 Mar 29
+-1 E %z 2024 Mar 31
+-2 E %z
Z America/Sitka 14:58:47 - LMT 1867 O 19 15:30
-9:1:13 - LMT 1900 Au 20 12
-8 - PST 1942
@@ -2918,15 +2917,21 @@ Z America/Thule -4:35:8 - LMT 1916 Jul 28
-4 Th A%sT
Z America/Tijuana -7:48:4 - LMT 1922 Ja 1 7u
-7 - MST 1924
--8 - PST 1927 Jun 10 23
+-8 - PST 1927 Jun 10
-7 - MST 1930 N 15
-8 - PST 1931 Ap
-8 1 PDT 1931 S 30
-8 - PST 1942 Ap 24
-8 1 PWT 1945 Au 14 23u
--8 1 PPT 1945 N 12
+-8 1 PPT 1945 N 15
-8 - PST 1948 Ap 5
-8 1 PDT 1949 Ja 14
+-8 - PST 1950 May
+-8 1 PDT 1950 S 24
+-8 - PST 1951 Ap 29 2
+-8 1 PDT 1951 S 30 2
+-8 - PST 1952 Ap 27 2
+-8 1 PDT 1952 S 28 2
-8 - PST 1954
-8 CA P%sT 1961
-8 - PST 1976
@@ -2961,31 +2966,31 @@ Z America/Yakutat 14:41:5 - LMT 1867 O 19 15:12:18
-9 u Y%sT 1983 N 30
-9 u AK%sT
Z Antarctica/Casey 0 - -00 1969
-8 - +08 2009 O 18 2
-11 - +11 2010 Mar 5 2
-8 - +08 2011 O 28 2
-11 - +11 2012 F 21 17u
-8 - +08 2016 O 22
-11 - +11 2018 Mar 11 4
-8 - +08 2018 O 7 4
-11 - +11 2019 Mar 17 3
-8 - +08 2019 O 4 3
-11 - +11 2020 Mar 8 3
-8 - +08 2020 O 4 0:1
-11 - +11 2021 Mar 14
-8 - +08 2021 O 3 0:1
-11 - +11 2022 Mar 13
-8 - +08 2022 O 2 0:1
-11 - +11 2023 Mar 9 3
-8 - +08
+8 - %z 2009 O 18 2
+11 - %z 2010 Mar 5 2
+8 - %z 2011 O 28 2
+11 - %z 2012 F 21 17u
+8 - %z 2016 O 22
+11 - %z 2018 Mar 11 4
+8 - %z 2018 O 7 4
+11 - %z 2019 Mar 17 3
+8 - %z 2019 O 4 3
+11 - %z 2020 Mar 8 3
+8 - %z 2020 O 4 0:1
+11 - %z 2021 Mar 14
+8 - %z 2021 O 3 0:1
+11 - %z 2022 Mar 13
+8 - %z 2022 O 2 0:1
+11 - %z 2023 Mar 9 3
+8 - %z
Z Antarctica/Davis 0 - -00 1957 Ja 13
-7 - +07 1964 N
+7 - %z 1964 N
0 - -00 1969 F
-7 - +07 2009 O 18 2
-5 - +05 2010 Mar 10 20u
-7 - +07 2011 O 28 2
-5 - +05 2012 F 21 20u
-7 - +07
+7 - %z 2009 O 18 2
+5 - %z 2010 Mar 10 20u
+7 - %z 2011 O 28 2
+5 - %z 2012 F 21 20u
+7 - %z
Z Antarctica/Macquarie 0 - -00 1899 N
10 - AEST 1916 O 1 2
10 1 AEDT 1917 F
@@ -2996,151 +3001,146 @@ Z Antarctica/Macquarie 0 - -00 1899 N
10 1 AEDT 2011
10 AT AE%sT
Z Antarctica/Mawson 0 - -00 1954 F 13
-6 - +06 2009 O 18 2
-5 - +05
+6 - %z 2009 O 18 2
+5 - %z
Z Antarctica/Palmer 0 - -00 1965
--4 A -04/-03 1969 O 5
--3 A -03/-02 1982 May
--4 x -04/-03 2016 D 4
--3 - -03
+-4 A %z 1969 O 5
+-3 A %z 1982 May
+-4 x %z 2016 D 4
+-3 - %z
Z Antarctica/Rothera 0 - -00 1976 D
--3 - -03
+-3 - %z
Z Antarctica/Troll 0 - -00 2005 F 12
0 Tr %s
Z Antarctica/Vostok 0 - -00 1957 D 16
-7 - +07 1994 F
+7 - %z 1994 F
0 - -00 1994 N
-7 - +07 2023 D 18 2
-5 - +05
+7 - %z 2023 D 18 2
+5 - %z
Z Asia/Almaty 5:7:48 - LMT 1924 May 2
-5 - +05 1930 Jun 21
-6 R +06/+07 1991 Mar 31 2s
-5 R +05/+06 1992 Ja 19 2s
-6 R +06/+07 2004 O 31 2s
-6 - +06 2024 Mar
-5 - +05
+5 - %z 1930 Jun 21
+6 R %z 1991 Mar 31 2s
+5 R %z 1992 Ja 19 2s
+6 R %z 2004 O 31 2s
+6 - %z 2024 Mar
+5 - %z
Z Asia/Amman 2:23:44 - LMT 1931
2 J EE%sT 2022 O 28 0s
-3 - +03
+3 - %z
Z Asia/Anadyr 11:49:56 - LMT 1924 May 2
-12 - +12 1930 Jun 21
-13 R +13/+14 1982 Ap 1 0s
-12 R +12/+13 1991 Mar 31 2s
-11 R +11/+12 1992 Ja 19 2s
-12 R +12/+13 2010 Mar 28 2s
-11 R +11/+12 2011 Mar 27 2s
-12 - +12
+12 - %z 1930 Jun 21
+13 R %z 1982 Ap 1 0s
+12 R %z 1991 Mar 31 2s
+11 R %z 1992 Ja 19 2s
+12 R %z 2010 Mar 28 2s
+11 R %z 2011 Mar 27 2s
+12 - %z
Z Asia/Aqtau 3:21:4 - LMT 1924 May 2
-4 - +04 1930 Jun 21
-5 - +05 1981 O
-6 - +06 1982 Ap
-5 R +05/+06 1991 Mar 31 2s
-4 R +04/+05 1992 Ja 19 2s
-5 R +05/+06 1994 S 25 2s
-4 R +04/+05 2004 O 31 2s
-5 - +05
+4 - %z 1930 Jun 21
+5 - %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1991 Mar 31 2s
+4 R %z 1992 Ja 19 2s
+5 R %z 1994 S 25 2s
+4 R %z 2004 O 31 2s
+5 - %z
Z Asia/Aqtobe 3:48:40 - LMT 1924 May 2
-4 - +04 1930 Jun 21
-5 - +05 1981 Ap
-5 1 +06 1981 O
-6 - +06 1982 Ap
-5 R +05/+06 1991 Mar 31 2s
-4 R +04/+05 1992 Ja 19 2s
-5 R +05/+06 2004 O 31 2s
-5 - +05
+4 - %z 1930 Jun 21
+5 - %z 1981 Ap
+5 1 %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1991 Mar 31 2s
+4 R %z 1992 Ja 19 2s
+5 R %z 2004 O 31 2s
+5 - %z
Z Asia/Ashgabat 3:53:32 - LMT 1924 May 2
-4 - +04 1930 Jun 21
-5 R +05/+06 1991 Mar 31 2
-4 R +04/+05 1992 Ja 19 2
-5 - +05
+4 - %z 1930 Jun 21
+5 R %z 1991 Mar 31 2
+4 R %z 1992 Ja 19 2
+5 - %z
Z Asia/Atyrau 3:27:44 - LMT 1924 May 2
-3 - +03 1930 Jun 21
-5 - +05 1981 O
-6 - +06 1982 Ap
-5 R +05/+06 1991 Mar 31 2s
-4 R +04/+05 1992 Ja 19 2s
-5 R +05/+06 1999 Mar 28 2s
-4 R +04/+05 2004 O 31 2s
-5 - +05
+3 - %z 1930 Jun 21
+5 - %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1991 Mar 31 2s
+4 R %z 1992 Ja 19 2s
+5 R %z 1999 Mar 28 2s
+4 R %z 2004 O 31 2s
+5 - %z
Z Asia/Baghdad 2:57:40 - LMT 1890
2:57:36 - BMT 1918
-3 - +03 1982 May
-3 IQ +03/+04
+3 - %z 1982 May
+3 IQ %z
Z Asia/Baku 3:19:24 - LMT 1924 May 2
-3 - +03 1957 Mar
-4 R +04/+05 1991 Mar 31 2s
-3 R +03/+04 1992 S lastSu 2s
-4 - +04 1996
-4 E +04/+05 1997
-4 AZ +04/+05
+3 - %z 1957 Mar
+4 R %z 1991 Mar 31 2s
+3 R %z 1992 S lastSu 2s
+4 - %z 1996
+4 E %z 1997
+4 AZ %z
Z Asia/Bangkok 6:42:4 - LMT 1880
6:42:4 - BMT 1920 Ap
-7 - +07
+7 - %z
Z Asia/Barnaul 5:35 - LMT 1919 D 10
-6 - +06 1930 Jun 21
-7 R +07/+08 1991 Mar 31 2s
-6 R +06/+07 1992 Ja 19 2s
-7 R +07/+08 1995 May 28
-6 R +06/+07 2011 Mar 27 2s
-7 - +07 2014 O 26 2s
-6 - +06 2016 Mar 27 2s
-7 - +07
+6 - %z 1930 Jun 21
+7 R %z 1991 Mar 31 2s
+6 R %z 1992 Ja 19 2s
+7 R %z 1995 May 28
+6 R %z 2011 Mar 27 2s
+7 - %z 2014 O 26 2s
+6 - %z 2016 Mar 27 2s
+7 - %z
Z Asia/Beirut 2:22 - LMT 1880
2 l EE%sT
Z Asia/Bishkek 4:58:24 - LMT 1924 May 2
-5 - +05 1930 Jun 21
-6 R +06/+07 1991 Mar 31 2s
-5 R +05/+06 1991 Au 31 2
-5 KG +05/+06 2005 Au 12
-6 - +06
+5 - %z 1930 Jun 21
+6 R %z 1991 Mar 31 2s
+5 R %z 1991 Au 31 2
+5 KG %z 2005 Au 12
+6 - %z
Z Asia/Chita 7:33:52 - LMT 1919 D 15
-8 - +08 1930 Jun 21
-9 R +09/+10 1991 Mar 31 2s
-8 R +08/+09 1992 Ja 19 2s
-9 R +09/+10 2011 Mar 27 2s
-10 - +10 2014 O 26 2s
-8 - +08 2016 Mar 27 2
-9 - +09
-Z Asia/Choibalsan 7:38 - LMT 1905 Au
-7 - +07 1978
-8 - +08 1983 Ap
-9 X +09/+10 2008 Mar 31
-8 X +08/+09
+8 - %z 1930 Jun 21
+9 R %z 1991 Mar 31 2s
+8 R %z 1992 Ja 19 2s
+9 R %z 2011 Mar 27 2s
+10 - %z 2014 O 26 2s
+8 - %z 2016 Mar 27 2
+9 - %z
Z Asia/Colombo 5:19:24 - LMT 1880
5:19:32 - MMT 1906
-5:30 - +0530 1942 Ja 5
-5:30 0:30 +06 1942 S
-5:30 1 +0630 1945 O 16 2
-5:30 - +0530 1996 May 25
-6:30 - +0630 1996 O 26 0:30
-6 - +06 2006 Ap 15 0:30
-5:30 - +0530
+5:30 - %z 1942 Ja 5
+5:30 0:30 %z 1942 S
+5:30 1 %z 1945 O 16 2
+5:30 - %z 1996 May 25
+6:30 - %z 1996 O 26 0:30
+6 - %z 2006 Ap 15 0:30
+5:30 - %z
Z Asia/Damascus 2:25:12 - LMT 1920
2 S EE%sT 2022 O 28
-3 - +03
+3 - %z
Z Asia/Dhaka 6:1:40 - LMT 1890
5:53:20 - HMT 1941 O
-6:30 - +0630 1942 May 15
-5:30 - +0530 1942 S
-6:30 - +0630 1951 S 30
-6 - +06 2009
-6 BD +06/+07
-Z Asia/Dili 8:22:20 - LMT 1912
-8 - +08 1942 F 21 23
-9 - +09 1976 May 3
-8 - +08 2000 S 17
-9 - +09
+6:30 - %z 1942 May 15
+5:30 - %z 1942 S
+6:30 - %z 1951 S 30
+6 - %z 2009
+6 BD %z
+Z Asia/Dili 8:22:20 - LMT 1911 D 31 16u
+8 - %z 1942 F 21 23
+9 - %z 1976 May 3
+8 - %z 2000 S 17
+9 - %z
Z Asia/Dubai 3:41:12 - LMT 1920
-4 - +04
+4 - %z
Z Asia/Dushanbe 4:35:12 - LMT 1924 May 2
-5 - +05 1930 Jun 21
-6 R +06/+07 1991 Mar 31 2s
-5 1 +06 1991 S 9 2s
-5 - +05
+5 - %z 1930 Jun 21
+6 R %z 1991 Mar 31 2s
+5 1 %z 1991 S 9 2s
+5 - %z
Z Asia/Famagusta 2:15:48 - LMT 1921 N 14
2 CY EE%sT 1998 S
2 E EE%sT 2016 S 8
-3 - +03 2017 O 29 1u
+3 - %z 2017 O 29 1u
2 E EE%sT
Z Asia/Gaza 2:17:52 - LMT 1900 O
2 Z EET/EEST 1948 May 15
@@ -3162,14 +3162,14 @@ Z Asia/Hebron 2:20:23 - LMT 1900 O
2 P EE%sT
Z Asia/Ho_Chi_Minh 7:6:30 - LMT 1906 Jul
7:6:30 - PLMT 1911 May
-7 - +07 1942 D 31 23
-8 - +08 1945 Mar 14 23
-9 - +09 1945 S 1 24
-7 - +07 1947 Ap
-8 - +08 1955 Jul 1 1
-7 - +07 1959 D 31 23
-8 - +08 1975 Jun 13
-7 - +07
+7 - %z 1942 D 31 23
+8 - %z 1945 Mar 14 23
+9 - %z 1945 S 1 24
+7 - %z 1947 Ap
+8 - %z 1955 Jul 1 1
+7 - %z 1959 D 31 23
+8 - %z 1975 Jun 13
+7 - %z
Z Asia/Hong_Kong 7:36:42 - LMT 1904 O 29 17u
8 - HKT 1941 Jun 15 3
8 1 HKST 1941 O 1 4
@@ -3177,96 +3177,96 @@ Z Asia/Hong_Kong 7:36:42 - LMT 1904 O 29 17u
9 - JST 1945 N 18 2
8 HK HK%sT
Z Asia/Hovd 6:6:36 - LMT 1905 Au
-6 - +06 1978
-7 X +07/+08
+6 - %z 1978
+7 X %z
Z Asia/Irkutsk 6:57:5 - LMT 1880
6:57:5 - IMT 1920 Ja 25
-7 - +07 1930 Jun 21
-8 R +08/+09 1991 Mar 31 2s
-7 R +07/+08 1992 Ja 19 2s
-8 R +08/+09 2011 Mar 27 2s
-9 - +09 2014 O 26 2s
-8 - +08
+7 - %z 1930 Jun 21
+8 R %z 1991 Mar 31 2s
+7 R %z 1992 Ja 19 2s
+8 R %z 2011 Mar 27 2s
+9 - %z 2014 O 26 2s
+8 - %z
Z Asia/Jakarta 7:7:12 - LMT 1867 Au 10
7:7:12 - BMT 1923 D 31 16:40u
-7:20 - +0720 1932 N
-7:30 - +0730 1942 Mar 23
-9 - +09 1945 S 23
-7:30 - +0730 1948 May
-8 - +08 1950 May
-7:30 - +0730 1964
+7:20 - %z 1932 N
+7:30 - %z 1942 Mar 23
+9 - %z 1945 S 23
+7:30 - %z 1948 May
+8 - %z 1950 May
+7:30 - %z 1964
7 - WIB
Z Asia/Jayapura 9:22:48 - LMT 1932 N
-9 - +09 1944 S
-9:30 - +0930 1964
+9 - %z 1944 S
+9:30 - %z 1964
9 - WIT
Z Asia/Jerusalem 2:20:54 - LMT 1880
2:20:40 - JMT 1918
2 Z I%sT
Z Asia/Kabul 4:36:48 - LMT 1890
-4 - +04 1945
-4:30 - +0430
+4 - %z 1945
+4:30 - %z
Z Asia/Kamchatka 10:34:36 - LMT 1922 N 10
-11 - +11 1930 Jun 21
-12 R +12/+13 1991 Mar 31 2s
-11 R +11/+12 1992 Ja 19 2s
-12 R +12/+13 2010 Mar 28 2s
-11 R +11/+12 2011 Mar 27 2s
-12 - +12
+11 - %z 1930 Jun 21
+12 R %z 1991 Mar 31 2s
+11 R %z 1992 Ja 19 2s
+12 R %z 2010 Mar 28 2s
+11 R %z 2011 Mar 27 2s
+12 - %z
Z Asia/Karachi 4:28:12 - LMT 1907
-5:30 - +0530 1942 S
-5:30 1 +0630 1945 O 15
-5:30 - +0530 1951 S 30
-5 - +05 1971 Mar 26
+5:30 - %z 1942 S
+5:30 1 %z 1945 O 15
+5:30 - %z 1951 S 30
+5 - %z 1971 Mar 26
5 PK PK%sT
Z Asia/Kathmandu 5:41:16 - LMT 1920
-5:30 - +0530 1986
-5:45 - +0545
+5:30 - %z 1986
+5:45 - %z
Z Asia/Khandyga 9:2:13 - LMT 1919 D 15
-8 - +08 1930 Jun 21
-9 R +09/+10 1991 Mar 31 2s
-8 R +08/+09 1992 Ja 19 2s
-9 R +09/+10 2004
-10 R +10/+11 2011 Mar 27 2s
-11 - +11 2011 S 13 0s
-10 - +10 2014 O 26 2s
-9 - +09
+8 - %z 1930 Jun 21
+9 R %z 1991 Mar 31 2s
+8 R %z 1992 Ja 19 2s
+9 R %z 2004
+10 R %z 2011 Mar 27 2s
+11 - %z 2011 S 13 0s
+10 - %z 2014 O 26 2s
+9 - %z
Z Asia/Kolkata 5:53:28 - LMT 1854 Jun 28
5:53:20 - HMT 1870
5:21:10 - MMT 1906
5:30 - IST 1941 O
-5:30 1 +0630 1942 May 15
+5:30 1 %z 1942 May 15
5:30 - IST 1942 S
-5:30 1 +0630 1945 O 15
+5:30 1 %z 1945 O 15
5:30 - IST
Z Asia/Krasnoyarsk 6:11:26 - LMT 1920 Ja 6
-6 - +06 1930 Jun 21
-7 R +07/+08 1991 Mar 31 2s
-6 R +06/+07 1992 Ja 19 2s
-7 R +07/+08 2011 Mar 27 2s
-8 - +08 2014 O 26 2s
-7 - +07
+6 - %z 1930 Jun 21
+7 R %z 1991 Mar 31 2s
+6 R %z 1992 Ja 19 2s
+7 R %z 2011 Mar 27 2s
+8 - %z 2014 O 26 2s
+7 - %z
Z Asia/Kuching 7:21:20 - LMT 1926 Mar
-7:30 - +0730 1933
-8 NB +08/+0820 1942 F 16
-9 - +09 1945 S 12
-8 - +08
+7:30 - %z 1933
+8 NB %z 1942 F 16
+9 - %z 1945 S 12
+8 - %z
Z Asia/Macau 7:34:10 - LMT 1904 O 30
8 - CST 1941 D 21 23
-9 _ +09/+10 1945 S 30 24
+9 _ %z 1945 S 30 24
8 _ C%sT
Z Asia/Magadan 10:3:12 - LMT 1924 May 2
-10 - +10 1930 Jun 21
-11 R +11/+12 1991 Mar 31 2s
-10 R +10/+11 1992 Ja 19 2s
-11 R +11/+12 2011 Mar 27 2s
-12 - +12 2014 O 26 2s
-10 - +10 2016 Ap 24 2s
-11 - +11
+10 - %z 1930 Jun 21
+11 R %z 1991 Mar 31 2s
+10 R %z 1992 Ja 19 2s
+11 R %z 2011 Mar 27 2s
+12 - %z 2014 O 26 2s
+10 - %z 2016 Ap 24 2s
+11 - %z
Z Asia/Makassar 7:57:36 - LMT 1920
7:57:36 - MMT 1932 N
-8 - +08 1942 F 9
-9 - +09 1945 S 23
+8 - %z 1942 F 9
+9 - %z 1945 S 23
8 - WITA
Z Asia/Manila -15:56 - LMT 1844 D 31
8:4 - LMT 1899 May 11
@@ -3277,45 +3277,45 @@ Z Asia/Nicosia 2:13:28 - LMT 1921 N 14
2 CY EE%sT 1998 S
2 E EE%sT
Z Asia/Novokuznetsk 5:48:48 - LMT 1924 May
-6 - +06 1930 Jun 21
-7 R +07/+08 1991 Mar 31 2s
-6 R +06/+07 1992 Ja 19 2s
-7 R +07/+08 2010 Mar 28 2s
-6 R +06/+07 2011 Mar 27 2s
-7 - +07
+6 - %z 1930 Jun 21
+7 R %z 1991 Mar 31 2s
+6 R %z 1992 Ja 19 2s
+7 R %z 2010 Mar 28 2s
+6 R %z 2011 Mar 27 2s
+7 - %z
Z Asia/Novosibirsk 5:31:40 - LMT 1919 D 14 6
-6 - +06 1930 Jun 21
-7 R +07/+08 1991 Mar 31 2s
-6 R +06/+07 1992 Ja 19 2s
-7 R +07/+08 1993 May 23
-6 R +06/+07 2011 Mar 27 2s
-7 - +07 2014 O 26 2s
-6 - +06 2016 Jul 24 2s
-7 - +07
+6 - %z 1930 Jun 21
+7 R %z 1991 Mar 31 2s
+6 R %z 1992 Ja 19 2s
+7 R %z 1993 May 23
+6 R %z 2011 Mar 27 2s
+7 - %z 2014 O 26 2s
+6 - %z 2016 Jul 24 2s
+7 - %z
Z Asia/Omsk 4:53:30 - LMT 1919 N 14
-5 - +05 1930 Jun 21
-6 R +06/+07 1991 Mar 31 2s
-5 R +05/+06 1992 Ja 19 2s
-6 R +06/+07 2011 Mar 27 2s
-7 - +07 2014 O 26 2s
-6 - +06
+5 - %z 1930 Jun 21
+6 R %z 1991 Mar 31 2s
+5 R %z 1992 Ja 19 2s
+6 R %z 2011 Mar 27 2s
+7 - %z 2014 O 26 2s
+6 - %z
Z Asia/Oral 3:25:24 - LMT 1924 May 2
-3 - +03 1930 Jun 21
-5 - +05 1981 Ap
-5 1 +06 1981 O
-6 - +06 1982 Ap
-5 R +05/+06 1989 Mar 26 2s
-4 R +04/+05 1992 Ja 19 2s
-5 R +05/+06 1992 Mar 29 2s
-4 R +04/+05 2004 O 31 2s
-5 - +05
+3 - %z 1930 Jun 21
+5 - %z 1981 Ap
+5 1 %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1989 Mar 26 2s
+4 R %z 1992 Ja 19 2s
+5 R %z 1992 Mar 29 2s
+4 R %z 2004 O 31 2s
+5 - %z
Z Asia/Pontianak 7:17:20 - LMT 1908 May
7:17:20 - PMT 1932 N
-7:30 - +0730 1942 Ja 29
-9 - +09 1945 S 23
-7:30 - +0730 1948 May
-8 - +08 1950 May
-7:30 - +0730 1964
+7:30 - %z 1942 Ja 29
+9 - %z 1945 S 23
+7:30 - %z 1948 May
+8 - %z 1950 May
+7:30 - %z 1964
8 - WITA 1988
7 - WIB
Z Asia/Pyongyang 8:23 - LMT 1908 Ap
@@ -3325,48 +3325,48 @@ Z Asia/Pyongyang 8:23 - LMT 1908 Ap
8:30 - KST 2018 May 4 23:30
9 - KST
Z Asia/Qatar 3:26:8 - LMT 1920
-4 - +04 1972 Jun
-3 - +03
+4 - %z 1972 Jun
+3 - %z
Z Asia/Qostanay 4:14:28 - LMT 1924 May 2
-4 - +04 1930 Jun 21
-5 - +05 1981 Ap
-5 1 +06 1981 O
-6 - +06 1982 Ap
-5 R +05/+06 1991 Mar 31 2s
-4 R +04/+05 1992 Ja 19 2s
-5 R +05/+06 2004 O 31 2s
-6 - +06 2024 Mar
-5 - +05
+4 - %z 1930 Jun 21
+5 - %z 1981 Ap
+5 1 %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1991 Mar 31 2s
+4 R %z 1992 Ja 19 2s
+5 R %z 2004 O 31 2s
+6 - %z 2024 Mar
+5 - %z
Z Asia/Qyzylorda 4:21:52 - LMT 1924 May 2
-4 - +04 1930 Jun 21
-5 - +05 1981 Ap
-5 1 +06 1981 O
-6 - +06 1982 Ap
-5 R +05/+06 1991 Mar 31 2s
-4 R +04/+05 1991 S 29 2s
-5 R +05/+06 1992 Ja 19 2s
-6 R +06/+07 1992 Mar 29 2s
-5 R +05/+06 2004 O 31 2s
-6 - +06 2018 D 21
-5 - +05
+4 - %z 1930 Jun 21
+5 - %z 1981 Ap
+5 1 %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1991 Mar 31 2s
+4 R %z 1991 S 29 2s
+5 R %z 1992 Ja 19 2s
+6 R %z 1992 Mar 29 2s
+5 R %z 2004 O 31 2s
+6 - %z 2018 D 21
+5 - %z
Z Asia/Riyadh 3:6:52 - LMT 1947 Mar 14
-3 - +03
+3 - %z
Z Asia/Sakhalin 9:30:48 - LMT 1905 Au 23
-9 - +09 1945 Au 25
-11 R +11/+12 1991 Mar 31 2s
-10 R +10/+11 1992 Ja 19 2s
-11 R +11/+12 1997 Mar lastSu 2s
-10 R +10/+11 2011 Mar 27 2s
-11 - +11 2014 O 26 2s
-10 - +10 2016 Mar 27 2s
-11 - +11
+9 - %z 1945 Au 25
+11 R %z 1991 Mar 31 2s
+10 R %z 1992 Ja 19 2s
+11 R %z 1997 Mar lastSu 2s
+10 R %z 2011 Mar 27 2s
+11 - %z 2014 O 26 2s
+10 - %z 2016 Mar 27 2s
+11 - %z
Z Asia/Samarkand 4:27:53 - LMT 1924 May 2
-4 - +04 1930 Jun 21
-5 - +05 1981 Ap
-5 1 +06 1981 O
-6 - +06 1982 Ap
-5 R +05/+06 1992
-5 - +05
+4 - %z 1930 Jun 21
+5 - %z 1981 Ap
+5 1 %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1992
+5 - %z
Z Asia/Seoul 8:27:52 - LMT 1908 Ap
8:30 - KST 1912
9 - JST 1945 S 8
@@ -3378,161 +3378,147 @@ Z Asia/Shanghai 8:5:43 - LMT 1901
8 CN C%sT
Z Asia/Singapore 6:55:25 - LMT 1901
6:55:25 - SMT 1905 Jun
-7 - +07 1933
-7 0:20 +0720 1936
-7:20 - +0720 1941 S
-7:30 - +0730 1942 F 16
-9 - +09 1945 S 12
-7:30 - +0730 1981 D 31 16u
-8 - +08
+7 - %z 1933
+7 0:20 %z 1936
+7:20 - %z 1941 S
+7:30 - %z 1942 F 16
+9 - %z 1945 S 12
+7:30 - %z 1981 D 31 16u
+8 - %z
Z Asia/Srednekolymsk 10:14:52 - LMT 1924 May 2
-10 - +10 1930 Jun 21
-11 R +11/+12 1991 Mar 31 2s
-10 R +10/+11 1992 Ja 19 2s
-11 R +11/+12 2011 Mar 27 2s
-12 - +12 2014 O 26 2s
-11 - +11
+10 - %z 1930 Jun 21
+11 R %z 1991 Mar 31 2s
+10 R %z 1992 Ja 19 2s
+11 R %z 2011 Mar 27 2s
+12 - %z 2014 O 26 2s
+11 - %z
Z Asia/Taipei 8:6 - LMT 1896
8 - CST 1937 O
9 - JST 1945 S 21 1
8 f C%sT
Z Asia/Tashkent 4:37:11 - LMT 1924 May 2
-5 - +05 1930 Jun 21
-6 R +06/+07 1991 Mar 31 2
-5 R +05/+06 1992
-5 - +05
+5 - %z 1930 Jun 21
+6 R %z 1991 Mar 31 2
+5 R %z 1992
+5 - %z
Z Asia/Tbilisi 2:59:11 - LMT 1880
2:59:11 - TBMT 1924 May 2
-3 - +03 1957 Mar
-4 R +04/+05 1991 Mar 31 2s
-3 R +03/+04 1992
-3 e +03/+04 1994 S lastSu
-4 e +04/+05 1996 O lastSu
-4 1 +05 1997 Mar lastSu
-4 e +04/+05 2004 Jun 27
-3 R +03/+04 2005 Mar lastSu 2
-4 - +04
+3 - %z 1957 Mar
+4 R %z 1991 Mar 31 2s
+3 R %z 1992
+3 e %z 1994 S lastSu
+4 e %z 1996 O lastSu
+4 1 %z 1997 Mar lastSu
+4 e %z 2004 Jun 27
+3 R %z 2005 Mar lastSu 2
+4 - %z
Z Asia/Tehran 3:25:44 - LMT 1916
3:25:44 - TMT 1935 Jun 13
-3:30 i +0330/+0430 1977 O 20 24
-4 i +04/+05 1979
-3:30 i +0330/+0430
+3:30 i %z 1977 O 20 24
+4 i %z 1979
+3:30 i %z
Z Asia/Thimphu 5:58:36 - LMT 1947 Au 15
-5:30 - +0530 1987 O
-6 - +06
+5:30 - %z 1987 O
+6 - %z
Z Asia/Tokyo 9:18:59 - LMT 1887 D 31 15u
9 JP J%sT
Z Asia/Tomsk 5:39:51 - LMT 1919 D 22
-6 - +06 1930 Jun 21
-7 R +07/+08 1991 Mar 31 2s
-6 R +06/+07 1992 Ja 19 2s
-7 R +07/+08 2002 May 1 3
-6 R +06/+07 2011 Mar 27 2s
-7 - +07 2014 O 26 2s
-6 - +06 2016 May 29 2s
-7 - +07
+6 - %z 1930 Jun 21
+7 R %z 1991 Mar 31 2s
+6 R %z 1992 Ja 19 2s
+7 R %z 2002 May 1 3
+6 R %z 2011 Mar 27 2s
+7 - %z 2014 O 26 2s
+6 - %z 2016 May 29 2s
+7 - %z
Z Asia/Ulaanbaatar 7:7:32 - LMT 1905 Au
-7 - +07 1978
-8 X +08/+09
+7 - %z 1978
+8 X %z
Z Asia/Urumqi 5:50:20 - LMT 1928
-6 - +06
+6 - %z
Z Asia/Ust-Nera 9:32:54 - LMT 1919 D 15
-8 - +08 1930 Jun 21
-9 R +09/+10 1981 Ap
-11 R +11/+12 1991 Mar 31 2s
-10 R +10/+11 1992 Ja 19 2s
-11 R +11/+12 2011 Mar 27 2s
-12 - +12 2011 S 13 0s
-11 - +11 2014 O 26 2s
-10 - +10
+8 - %z 1930 Jun 21
+9 R %z 1981 Ap
+11 R %z 1991 Mar 31 2s
+10 R %z 1992 Ja 19 2s
+11 R %z 2011 Mar 27 2s
+12 - %z 2011 S 13 0s
+11 - %z 2014 O 26 2s
+10 - %z
Z Asia/Vladivostok 8:47:31 - LMT 1922 N 15
-9 - +09 1930 Jun 21
-10 R +10/+11 1991 Mar 31 2s
-9 R +09/+10 1992 Ja 19 2s
-10 R +10/+11 2011 Mar 27 2s
-11 - +11 2014 O 26 2s
-10 - +10
+9 - %z 1930 Jun 21
+10 R %z 1991 Mar 31 2s
+9 R %z 1992 Ja 19 2s
+10 R %z 2011 Mar 27 2s
+11 - %z 2014 O 26 2s
+10 - %z
Z Asia/Yakutsk 8:38:58 - LMT 1919 D 15
-8 - +08 1930 Jun 21
-9 R +09/+10 1991 Mar 31 2s
-8 R +08/+09 1992 Ja 19 2s
-9 R +09/+10 2011 Mar 27 2s
-10 - +10 2014 O 26 2s
-9 - +09
+8 - %z 1930 Jun 21
+9 R %z 1991 Mar 31 2s
+8 R %z 1992 Ja 19 2s
+9 R %z 2011 Mar 27 2s
+10 - %z 2014 O 26 2s
+9 - %z
Z Asia/Yangon 6:24:47 - LMT 1880
6:24:47 - RMT 1920
-6:30 - +0630 1942 May
-9 - +09 1945 May 3
-6:30 - +0630
+6:30 - %z 1942 May
+9 - %z 1945 May 3
+6:30 - %z
Z Asia/Yekaterinburg 4:2:33 - LMT 1916 Jul 3
3:45:5 - PMT 1919 Jul 15 4
-4 - +04 1930 Jun 21
-5 R +05/+06 1991 Mar 31 2s
-4 R +04/+05 1992 Ja 19 2s
-5 R +05/+06 2011 Mar 27 2s
-6 - +06 2014 O 26 2s
-5 - +05
+4 - %z 1930 Jun 21
+5 R %z 1991 Mar 31 2s
+4 R %z 1992 Ja 19 2s
+5 R %z 2011 Mar 27 2s
+6 - %z 2014 O 26 2s
+5 - %z
Z Asia/Yerevan 2:58 - LMT 1924 May 2
-3 - +03 1957 Mar
-4 R +04/+05 1991 Mar 31 2s
-3 R +03/+04 1995 S 24 2s
-4 - +04 1997
-4 R +04/+05 2011
-4 AM +04/+05
+3 - %z 1957 Mar
+4 R %z 1991 Mar 31 2s
+3 R %z 1995 S 24 2s
+4 - %z 1997
+4 R %z 2011
+4 AM %z
Z Atlantic/Azores -1:42:40 - LMT 1884
-1:54:32 - HMT 1912 Ja 1 2u
--2 p -02/-01 1942 Ap 25 22s
--2 p +00 1942 Au 15 22s
--2 p -02/-01 1943 Ap 17 22s
--2 p +00 1943 Au 28 22s
--2 p -02/-01 1944 Ap 22 22s
--2 p +00 1944 Au 26 22s
--2 p -02/-01 1945 Ap 21 22s
--2 p +00 1945 Au 25 22s
--2 p -02/-01 1966 Ap 3 2
--1 p -01/+00 1983 S 25 1s
--1 W- -01/+00 1992 S 27 1s
-0 E WE%sT 1993 Mar 28 1u
--1 E -01/+00
+-2 p %z 1966 O 2 2s
+-1 - %z 1982 Mar 28 0s
+-1 p %z 1986
+-1 E %z 1992 D 27 1s
+0 E WE%sT 1993 Jun 17 1u
+-1 E %z
Z Atlantic/Bermuda -4:19:18 - LMT 1890
-4:19:18 Be BMT/BST 1930 Ja 1 2
-4 Be A%sT 1974 Ap 28 2
-4 C A%sT 1976
-4 u A%sT
Z Atlantic/Canary -1:1:36 - LMT 1922 Mar
--1 - -01 1946 S 30 1
+-1 - %z 1946 S 30 1
0 - WET 1980 Ap 6 0s
0 1 WEST 1980 S 28 1u
0 E WE%sT
Z Atlantic/Cape_Verde -1:34:4 - LMT 1912 Ja 1 2u
--2 - -02 1942 S
--2 1 -01 1945 O 15
--2 - -02 1975 N 25 2
--1 - -01
+-2 - %z 1942 S
+-2 1 %z 1945 O 15
+-2 - %z 1975 N 25 2
+-1 - %z
Z Atlantic/Faroe -0:27:4 - LMT 1908 Ja 11
0 - WET 1981
0 E WE%sT
Z Atlantic/Madeira -1:7:36 - LMT 1884
-1:7:36 - FMT 1912 Ja 1 1u
--1 p -01/+00 1942 Ap 25 22s
--1 p +01 1942 Au 15 22s
--1 p -01/+00 1943 Ap 17 22s
--1 p +01 1943 Au 28 22s
--1 p -01/+00 1944 Ap 22 22s
--1 p +01 1944 Au 26 22s
--1 p -01/+00 1945 Ap 21 22s
--1 p +01 1945 Au 25 22s
--1 p -01/+00 1966 Ap 3 2
-0 p WE%sT 1983 S 25 1s
+-1 p %z 1966 O 2 2s
+0 - WET 1982 Ap 4
+0 p WE%sT 1986 Jul 31
0 E WE%sT
Z Atlantic/South_Georgia -2:26:8 - LMT 1890
--2 - -02
+-2 - %z
Z Atlantic/Stanley -3:51:24 - LMT 1890
-3:51:24 - SMT 1912 Mar 12
--4 FK -04/-03 1983 May
--3 FK -03/-02 1985 S 15
--4 FK -04/-03 2010 S 5 2
--3 - -03
+-4 FK %z 1983 May
+-3 FK %z 1985 S 15
+-4 FK %z 2010 S 5 2
+-3 - %z
Z Australia/Adelaide 9:14:20 - LMT 1895 F
9 - ACST 1899 May
9:30 AU AC%sT 1971
@@ -3550,8 +3536,8 @@ Z Australia/Darwin 8:43:20 - LMT 1895 F
9 - ACST 1899 May
9:30 AU AC%sT
Z Australia/Eucla 8:35:28 - LMT 1895 D
-8:45 AU +0845/+0945 1943 Jul
-8:45 AW +0845/+0945
+8:45 AU %z 1943 Jul
+8:45 AW %z
Z Australia/Hobart 9:49:16 - LMT 1895 S
10 AT AE%sT 1919 O 24
10 AU AE%sT 1967
@@ -3562,8 +3548,8 @@ Z Australia/Lindeman 9:55:56 - LMT 1895
10 Ho AE%sT
Z Australia/Lord_Howe 10:36:20 - LMT 1895 F
10 - AEST 1981 Mar
-10:30 LH +1030/+1130 1985 Jul
-10:30 LH +1030/+11
+10:30 LH %z 1985 Jul
+10:30 LH %z
Z Australia/Melbourne 9:39:52 - LMT 1895 F
10 AU AE%sT 1971
10 AV AE%sT
@@ -3573,52 +3559,47 @@ Z Australia/Perth 7:43:24 - LMT 1895 D
Z Australia/Sydney 10:4:52 - LMT 1895 F
10 AU AE%sT 1971
10 AN AE%sT
-Z CET 1 c CE%sT
-Z CST6CDT -6 u C%sT
-Z EET 2 E EE%sT
-Z EST -5 - EST
-Z EST5EDT -5 u E%sT
Z Etc/GMT 0 - GMT
-Z Etc/GMT+1 -1 - -01
-Z Etc/GMT+10 -10 - -10
-Z Etc/GMT+11 -11 - -11
-Z Etc/GMT+12 -12 - -12
-Z Etc/GMT+2 -2 - -02
-Z Etc/GMT+3 -3 - -03
-Z Etc/GMT+4 -4 - -04
-Z Etc/GMT+5 -5 - -05
-Z Etc/GMT+6 -6 - -06
-Z Etc/GMT+7 -7 - -07
-Z Etc/GMT+8 -8 - -08
-Z Etc/GMT+9 -9 - -09
-Z Etc/GMT-1 1 - +01
-Z Etc/GMT-10 10 - +10
-Z Etc/GMT-11 11 - +11
-Z Etc/GMT-12 12 - +12
-Z Etc/GMT-13 13 - +13
-Z Etc/GMT-14 14 - +14
-Z Etc/GMT-2 2 - +02
-Z Etc/GMT-3 3 - +03
-Z Etc/GMT-4 4 - +04
-Z Etc/GMT-5 5 - +05
-Z Etc/GMT-6 6 - +06
-Z Etc/GMT-7 7 - +07
-Z Etc/GMT-8 8 - +08
-Z Etc/GMT-9 9 - +09
+Z Etc/GMT+1 -1 - %z
+Z Etc/GMT+10 -10 - %z
+Z Etc/GMT+11 -11 - %z
+Z Etc/GMT+12 -12 - %z
+Z Etc/GMT+2 -2 - %z
+Z Etc/GMT+3 -3 - %z
+Z Etc/GMT+4 -4 - %z
+Z Etc/GMT+5 -5 - %z
+Z Etc/GMT+6 -6 - %z
+Z Etc/GMT+7 -7 - %z
+Z Etc/GMT+8 -8 - %z
+Z Etc/GMT+9 -9 - %z
+Z Etc/GMT-1 1 - %z
+Z Etc/GMT-10 10 - %z
+Z Etc/GMT-11 11 - %z
+Z Etc/GMT-12 12 - %z
+Z Etc/GMT-13 13 - %z
+Z Etc/GMT-14 14 - %z
+Z Etc/GMT-2 2 - %z
+Z Etc/GMT-3 3 - %z
+Z Etc/GMT-4 4 - %z
+Z Etc/GMT-5 5 - %z
+Z Etc/GMT-6 6 - %z
+Z Etc/GMT-7 7 - %z
+Z Etc/GMT-8 8 - %z
+Z Etc/GMT-9 9 - %z
Z Etc/UTC 0 - UTC
Z Europe/Andorra 0:6:4 - LMT 1901
0 - WET 1946 S 30
1 - CET 1985 Mar 31 2
1 E CE%sT
Z Europe/Astrakhan 3:12:12 - LMT 1924 May
-3 - +03 1930 Jun 21
-4 R +04/+05 1989 Mar 26 2s
-3 R +03/+04 1991 Mar 31 2s
-4 - +04 1992 Mar 29 2s
-3 R +03/+04 2011 Mar 27 2s
-4 - +04 2014 O 26 2s
-3 - +03 2016 Mar 27 2s
-4 - +04
+3 - %z 1930 Jun 21
+4 R %z 1989 Mar 26 2s
+3 R %z 1991 Mar 31 2s
+4 - %z 1992 Mar 29 2s
+3 R %z 2011 Mar 27 2s
+4 - %z 2014 O 26 2s
+3 - %z 2016 Mar 27 2s
+4 - %z
Z Europe/Athens 1:34:52 - LMT 1895 S 14
1:34:52 - AMT 1916 Jul 28 0:1
2 g EE%sT 1941 Ap 30
@@ -3691,7 +3672,7 @@ Z Europe/Helsinki 1:39:49 - LMT 1878 May 31
Z Europe/Istanbul 1:55:52 - LMT 1880
1:56:56 - IMT 1910 O
2 T EE%sT 1978 Jun 29
-3 T +03/+04 1984 N 1 2
+3 T %z 1984 N 1 2
2 T EE%sT 2007
2 E EE%sT 2011 Mar 27 1u
2 - EET 2011 Mar 28 1u
@@ -3700,19 +3681,19 @@ Z Europe/Istanbul 1:55:52 - LMT 1880
2 E EE%sT 2015 O 25 1u
2 1 EEST 2015 N 8 1u
2 E EE%sT 2016 S 7
-3 - +03
+3 - %z
Z Europe/Kaliningrad 1:22 - LMT 1893 Ap
1 c CE%sT 1945 Ap 10
2 O EE%sT 1946 Ap 7
3 R MSK/MSD 1989 Mar 26 2s
2 R EE%sT 2011 Mar 27 2s
-3 - +03 2014 O 26 2s
+3 - %z 2014 O 26 2s
2 - EET
Z Europe/Kirov 3:18:48 - LMT 1919 Jul 1 0u
-3 - +03 1930 Jun 21
-4 R +04/+05 1989 Mar 26 2s
+3 - %z 1930 Jun 21
+4 R %z 1989 Mar 26 2s
3 R MSK/MSD 1991 Mar 31 2s
-4 - +04 1992 Mar 29 2s
+4 - %z 1992 Mar 29 2s
3 R MSK/MSD 2011 Mar 27 2s
4 - MSK 2014 O 26 2s
3 - MSK
@@ -3727,10 +3708,10 @@ Z Europe/Kyiv 2:2:4 - LMT 1880
2 E EE%sT
Z Europe/Lisbon -0:36:45 - LMT 1884
-0:36:45 - LMT 1912 Ja 1 0u
-0 p WE%sT 1966 Ap 3 2
+0 p WE%sT 1966 O 2 2s
1 - CET 1976 S 26 1
-0 p WE%sT 1983 S 25 1s
-0 W- WE%sT 1992 S 27 1s
+0 p WE%sT 1986
+0 E WE%sT 1992 S 27 1u
1 E CE%sT 1996 Mar 31 1u
0 E WE%sT
Z Europe/London -0:1:15 - LMT 1847 D
@@ -3754,7 +3735,7 @@ Z Europe/Minsk 1:50:16 - LMT 1880
3 R MSK/MSD 1990
3 - MSK 1991 Mar 31 2s
2 R EE%sT 2011 Mar 27 2s
-3 - +03
+3 - %z
Z Europe/Moscow 2:30:17 - LMT 1880
2:30:17 - MMT 1916 Jul 3
2:31:19 R %s 1919 Jul 1 0u
@@ -3802,24 +3783,24 @@ Z Europe/Rome 0:49:56 - LMT 1866 D 12
1 I CE%sT 1980
1 E CE%sT
Z Europe/Samara 3:20:20 - LMT 1919 Jul 1 0u
-3 - +03 1930 Jun 21
-4 - +04 1935 Ja 27
-4 R +04/+05 1989 Mar 26 2s
-3 R +03/+04 1991 Mar 31 2s
-2 R +02/+03 1991 S 29 2s
-3 - +03 1991 O 20 3
-4 R +04/+05 2010 Mar 28 2s
-3 R +03/+04 2011 Mar 27 2s
-4 - +04
+3 - %z 1930 Jun 21
+4 - %z 1935 Ja 27
+4 R %z 1989 Mar 26 2s
+3 R %z 1991 Mar 31 2s
+2 R %z 1991 S 29 2s
+3 - %z 1991 O 20 3
+4 R %z 2010 Mar 28 2s
+3 R %z 2011 Mar 27 2s
+4 - %z
Z Europe/Saratov 3:4:18 - LMT 1919 Jul 1 0u
-3 - +03 1930 Jun 21
-4 R +04/+05 1988 Mar 27 2s
-3 R +03/+04 1991 Mar 31 2s
-4 - +04 1992 Mar 29 2s
-3 R +03/+04 2011 Mar 27 2s
-4 - +04 2014 O 26 2s
-3 - +03 2016 D 4 2s
-4 - +04
+3 - %z 1930 Jun 21
+4 R %z 1988 Mar 27 2s
+3 R %z 1991 Mar 31 2s
+4 - %z 1992 Mar 29 2s
+3 R %z 2011 Mar 27 2s
+4 - %z 2014 O 26 2s
+3 - %z 2016 D 4 2s
+4 - %z
Z Europe/Simferopol 2:16:24 - LMT 1880
2:16 - SMT 1924 May 2
2 - EET 1930 Jun 21
@@ -3863,14 +3844,14 @@ Z Europe/Tirane 1:19:20 - LMT 1914
1 q CE%sT 1984 Jul
1 E CE%sT
Z Europe/Ulyanovsk 3:13:36 - LMT 1919 Jul 1 0u
-3 - +03 1930 Jun 21
-4 R +04/+05 1989 Mar 26 2s
-3 R +03/+04 1991 Mar 31 2s
-2 R +02/+03 1992 Ja 19 2s
-3 R +03/+04 2011 Mar 27 2s
-4 - +04 2014 O 26 2s
-3 - +03 2016 Mar 27 2s
-4 - +04
+3 - %z 1930 Jun 21
+4 R %z 1989 Mar 26 2s
+3 R %z 1991 Mar 31 2s
+2 R %z 1992 Ja 19 2s
+3 R %z 2011 Mar 27 2s
+4 - %z 2014 O 26 2s
+3 - %z 2016 Mar 27 2s
+4 - %z
Z Europe/Vienna 1:5:21 - LMT 1893 Ap
1 c CE%sT 1920
1 a CE%sT 1940 Ap 1 2s
@@ -3895,15 +3876,15 @@ Z Europe/Vilnius 1:41:16 - LMT 1880
2 - EET 2003
2 E EE%sT
Z Europe/Volgograd 2:57:40 - LMT 1920 Ja 3
-3 - +03 1930 Jun 21
-4 - +04 1961 N 11
-4 R +04/+05 1988 Mar 27 2s
+3 - %z 1930 Jun 21
+4 - %z 1961 N 11
+4 R %z 1988 Mar 27 2s
3 R MSK/MSD 1991 Mar 31 2s
-4 - +04 1992 Mar 29 2s
+4 - %z 1992 Mar 29 2s
3 R MSK/MSD 2011 Mar 27 2s
4 - MSK 2014 O 26 2s
3 - MSK 2018 O 28 2s
-4 - +04 2020 D 27 2s
+4 - %z 2020 D 27 2s
3 - MSK
Z Europe/Warsaw 1:24 - LMT 1880
1:24 - WMT 1915 Au 5
@@ -3919,58 +3900,53 @@ Z Europe/Zurich 0:34:8 - LMT 1853 Jul 16
1 CH CE%sT 1981
1 E CE%sT
Z Factory 0 - -00
-Z HST -10 - HST
Z Indian/Chagos 4:49:40 - LMT 1907
-5 - +05 1996
-6 - +06
+5 - %z 1996
+6 - %z
Z Indian/Maldives 4:54 - LMT 1880
4:54 - MMT 1960
-5 - +05
+5 - %z
Z Indian/Mauritius 3:50 - LMT 1907
-4 MU +04/+05
-Z MET 1 c ME%sT
-Z MST -7 - MST
-Z MST7MDT -7 u M%sT
-Z PST8PDT -8 u P%sT
+4 MU %z
Z Pacific/Apia 12:33:4 - LMT 1892 Jul 5
-11:26:56 - LMT 1911
--11:30 - -1130 1950
--11 WS -11/-10 2011 D 29 24
-13 WS +13/+14
+-11:30 - %z 1950
+-11 WS %z 2011 D 29 24
+13 WS %z
Z Pacific/Auckland 11:39:4 - LMT 1868 N 2
11:30 NZ NZ%sT 1946
12 NZ NZ%sT
Z Pacific/Bougainville 10:22:16 - LMT 1880
9:48:32 - PMMT 1895
-10 - +10 1942 Jul
-9 - +09 1945 Au 21
-10 - +10 2014 D 28 2
-11 - +11
+10 - %z 1942 Jul
+9 - %z 1945 Au 21
+10 - %z 2014 D 28 2
+11 - %z
Z Pacific/Chatham 12:13:48 - LMT 1868 N 2
-12:15 - +1215 1946
-12:45 k +1245/+1345
+12:15 - %z 1946
+12:45 k %z
Z Pacific/Easter -7:17:28 - LMT 1890
-7:17:28 - EMT 1932 S
--7 x -07/-06 1982 Mar 14 3u
--6 x -06/-05
+-7 x %z 1982 Mar 14 3u
+-6 x %z
Z Pacific/Efate 11:13:16 - LMT 1912 Ja 13
-11 VU +11/+12
+11 VU %z
Z Pacific/Fakaofo -11:24:56 - LMT 1901
--11 - -11 2011 D 30
-13 - +13
+-11 - %z 2011 D 30
+13 - %z
Z Pacific/Fiji 11:55:44 - LMT 1915 O 26
-12 FJ +12/+13
+12 FJ %z
Z Pacific/Galapagos -5:58:24 - LMT 1931
--5 - -05 1986
--6 EC -06/-05
+-5 - %z 1986
+-6 EC %z
Z Pacific/Gambier -8:59:48 - LMT 1912 O
--9 - -09
+-9 - %z
Z Pacific/Guadalcanal 10:39:48 - LMT 1912 O
-11 - +11
+11 - %z
Z Pacific/Guam -14:21 - LMT 1844 D 31
9:39 - LMT 1901
10 - GST 1941 D 10
-9 - +09 1944 Jul 31
+9 - %z 1944 Jul 31
10 Gu G%sT 2000 D 23
10 - ChST
Z Pacific/Honolulu -10:31:26 - LMT 1896 Ja 13 12
@@ -3979,74 +3955,73 @@ Z Pacific/Honolulu -10:31:26 - LMT 1896 Ja 13 12
-10:30 u H%sT 1947 Jun 8 2
-10 - HST
Z Pacific/Kanton 0 - -00 1937 Au 31
--12 - -12 1979 O
--11 - -11 1994 D 31
-13 - +13
+-12 - %z 1979 O
+-11 - %z 1994 D 31
+13 - %z
Z Pacific/Kiritimati -10:29:20 - LMT 1901
--10:40 - -1040 1979 O
--10 - -10 1994 D 31
-14 - +14
+-10:40 - %z 1979 O
+-10 - %z 1994 D 31
+14 - %z
Z Pacific/Kosrae -13:8:4 - LMT 1844 D 31
10:51:56 - LMT 1901
-11 - +11 1914 O
-9 - +09 1919 F
-11 - +11 1937
-10 - +10 1941 Ap
-9 - +09 1945 Au
-11 - +11 1969 O
-12 - +12 1999
-11 - +11
+11 - %z 1914 O
+9 - %z 1919 F
+11 - %z 1937
+10 - %z 1941 Ap
+9 - %z 1945 Au
+11 - %z 1969 O
+12 - %z 1999
+11 - %z
Z Pacific/Kwajalein 11:9:20 - LMT 1901
-11 - +11 1937
-10 - +10 1941 Ap
-9 - +09 1944 F 6
-11 - +11 1969 O
--12 - -12 1993 Au 20 24
-12 - +12
+11 - %z 1937
+10 - %z 1941 Ap
+9 - %z 1944 F 6
+11 - %z 1969 O
+-12 - %z 1993 Au 20 24
+12 - %z
Z Pacific/Marquesas -9:18 - LMT 1912 O
--9:30 - -0930
+-9:30 - %z
Z Pacific/Nauru 11:7:40 - LMT 1921 Ja 15
-11:30 - +1130 1942 Au 29
-9 - +09 1945 S 8
-11:30 - +1130 1979 F 10 2
-12 - +12
+11:30 - %z 1942 Au 29
+9 - %z 1945 S 8
+11:30 - %z 1979 F 10 2
+12 - %z
Z Pacific/Niue -11:19:40 - LMT 1952 O 16
--11:20 - -1120 1964 Jul
--11 - -11
+-11:20 - %z 1964 Jul
+-11 - %z
Z Pacific/Norfolk 11:11:52 - LMT 1901
-11:12 - +1112 1951
-11:30 - +1130 1974 O 27 2s
-11:30 1 +1230 1975 Mar 2 2s
-11:30 - +1130 2015 O 4 2s
-11 - +11 2019 Jul
-11 AN +11/+12
+11:12 - %z 1951
+11:30 - %z 1974 O 27 2s
+11:30 1 %z 1975 Mar 2 2s
+11:30 - %z 2015 O 4 2s
+11 - %z 2019 Jul
+11 AN %z
Z Pacific/Noumea 11:5:48 - LMT 1912 Ja 13
-11 NC +11/+12
+11 NC %z
Z Pacific/Pago_Pago 12:37:12 - LMT 1892 Jul 5
-11:22:48 - LMT 1911
-11 - SST
Z Pacific/Palau -15:2:4 - LMT 1844 D 31
8:57:56 - LMT 1901
-9 - +09
+9 - %z
Z Pacific/Pitcairn -8:40:20 - LMT 1901
--8:30 - -0830 1998 Ap 27
--8 - -08
+-8:30 - %z 1998 Ap 27
+-8 - %z
Z Pacific/Port_Moresby 9:48:40 - LMT 1880
9:48:32 - PMMT 1895
-10 - +10
+10 - %z
Z Pacific/Rarotonga 13:20:56 - LMT 1899 D 26
-10:39:4 - LMT 1952 O 16
--10:30 - -1030 1978 N 12
--10 CK -10/-0930
+-10:30 - %z 1978 N 12
+-10 CK %z
Z Pacific/Tahiti -9:58:16 - LMT 1912 O
--10 - -10
+-10 - %z
Z Pacific/Tarawa 11:32:4 - LMT 1901
-12 - +12
+12 - %z
Z Pacific/Tongatapu 12:19:12 - LMT 1945 S 10
-12:20 - +1220 1961
-13 - +13 1999
-13 TO +13/+14
-Z WET 0 E WE%sT
+12:20 - %z 1961
+13 - %z 1999
+13 TO %z
L Etc/GMT GMT
L Australia/Sydney Australia/ACT
L Australia/Lord_Howe Australia/LHI
@@ -4062,6 +4037,8 @@ L America/Rio_Branco Brazil/Acre
L America/Noronha Brazil/DeNoronha
L America/Sao_Paulo Brazil/East
L America/Manaus Brazil/West
+L Europe/Brussels CET
+L America/Chicago CST6CDT
L America/Halifax Canada/Atlantic
L America/Winnipeg Canada/Central
L America/Toronto Canada/Eastern
@@ -4073,6 +4050,9 @@ L America/Whitehorse Canada/Yukon
L America/Santiago Chile/Continental
L Pacific/Easter Chile/EasterIsland
L America/Havana Cuba
+L Europe/Athens EET
+L America/Panama EST
+L America/New_York EST5EDT
L Africa/Cairo Egypt
L Europe/Dublin Eire
L Etc/GMT Etc/GMT+0
@@ -4096,6 +4076,9 @@ L America/Jamaica Jamaica
L Asia/Tokyo Japan
L Pacific/Kwajalein Kwajalein
L Africa/Tripoli Libya
+L Europe/Brussels MET
+L America/Phoenix MST
+L America/Denver MST7MDT
L America/Tijuana Mexico/BajaNorte
L America/Mazatlan Mexico/BajaSur
L America/Mexico_City Mexico/General
@@ -4259,6 +4242,7 @@ L America/Denver America/Shiprock
L America/Toronto America/Thunder_Bay
L America/Edmonton America/Yellowknife
L Pacific/Auckland Antarctica/South_Pole
+L Asia/Ulaanbaatar Asia/Choibalsan
L Asia/Shanghai Asia/Chongqing
L Asia/Shanghai Asia/Harbin
L Asia/Urumqi Asia/Kashgar
@@ -4273,6 +4257,7 @@ L Europe/Kyiv Europe/Zaporozhye
L Pacific/Kanton Pacific/Enderbury
L Pacific/Honolulu Pacific/Johnston
L Pacific/Port_Moresby Pacific/Yap
+L Europe/Lisbon WET
L Africa/Nairobi Africa/Asmera
L America/Nuuk America/Godthab
L Asia/Ashgabat Asia/Ashkhabad
@@ -4290,5 +4275,7 @@ L Asia/Ulaanbaatar Asia/Ulan_Bator
L Atlantic/Faroe Atlantic/Faeroe
L Europe/Kyiv Europe/Kiev
L Asia/Nicosia Europe/Nicosia
+L Pacific/Honolulu HST
+L America/Los_Angeles PST8PDT
L Pacific/Guadalcanal Pacific/Ponape
L Pacific/Port_Moresby Pacific/Truk
diff --git a/lib/pytz/zoneinfo/zone.tab b/lib/pytz/zoneinfo/zone.tab
index 3fa9306a..bfc0b593 100644
--- a/lib/pytz/zoneinfo/zone.tab
+++ b/lib/pytz/zoneinfo/zone.tab
@@ -264,8 +264,7 @@ MK +4159+02126 Europe/Skopje
ML +1239-00800 Africa/Bamako
MM +1647+09610 Asia/Yangon
MN +4755+10653 Asia/Ulaanbaatar most of Mongolia
-MN +4801+09139 Asia/Hovd Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan
-MN +4804+11430 Asia/Choibalsan Dornod, Sukhbaatar
+MN +4801+09139 Asia/Hovd Bayan-Olgii, Hovd, Uvs
MO +221150+1133230 Asia/Macau
MP +1512+14545 Pacific/Saipan
MQ +1436-06105 America/Martinique
diff --git a/lib/pytz/zoneinfo/zone1970.tab b/lib/pytz/zoneinfo/zone1970.tab
index abd94897..7726f39a 100644
--- a/lib/pytz/zoneinfo/zone1970.tab
+++ b/lib/pytz/zoneinfo/zone1970.tab
@@ -209,8 +209,7 @@ MD +4700+02850 Europe/Chisinau
MH +0905+16720 Pacific/Kwajalein Kwajalein
MM,CC +1647+09610 Asia/Yangon
MN +4755+10653 Asia/Ulaanbaatar most of Mongolia
-MN +4801+09139 Asia/Hovd Bayan-Ölgii, Govi-Altai, Hovd, Uvs, Zavkhan
-MN +4804+11430 Asia/Choibalsan Dornod, Sükhbaatar
+MN +4801+09139 Asia/Hovd Bayan-Ölgii, Hovd, Uvs
MO +221150+1133230 Asia/Macau
MQ +1436-06105 America/Martinique
MT +3554+01431 Europe/Malta
diff --git a/lib/pytz/zoneinfo/zonenow.tab b/lib/pytz/zoneinfo/zonenow.tab
index b6f29109..01f536b3 100644
--- a/lib/pytz/zoneinfo/zonenow.tab
+++ b/lib/pytz/zoneinfo/zonenow.tab
@@ -5,7 +5,7 @@
# From Paul Eggert (2023-12-18):
# This file contains a table where each row stands for a timezone
# where civil timestamps are predicted to agree from now on.
-# This file is like zone1970.tab (see zone1970.tab's coments),
+# This file is like zone1970.tab (see zone1970.tab's comments),
# but with the following changes:
#
# 1. Each timezone corresponds to a set of clocks that are planned
@@ -123,8 +123,6 @@ XX +1455-02331 Atlantic/Cape_Verde Cape Verde
#
# -01/+00 (EU DST)
XX +3744-02540 Atlantic/Azores Azores
-# -01/+00 (EU DST) until 2024-03-31; then -02/-01 (EU DST)
-XX +7029-02158 America/Scoresbysund Ittoqqortoormiit
#
# +00 - GMT
XX +0519-00402 Africa/Abidjan far western Africa; Iceland ("GMT")
@@ -199,7 +197,7 @@ XX +2518+05518 Asia/Dubai Russia; Caucasus; Persian Gulf; Seychelles; Réunion
XX +3431+06912 Asia/Kabul Afghanistan
#
# +05
-XX +4120+06918 Asia/Tashkent Russia; west Kazakhstan; Tajikistan; Turkmenistan; Uzbekistan; Maldives
+XX +4120+06918 Asia/Tashkent Russia; Kazakhstan; Tajikistan; Turkmenistan; Uzbekistan; Maldives
#
# +05 - PKT
XX +2452+06703 Asia/Karachi Pakistan ("PKT")
@@ -215,8 +213,6 @@ XX +2743+08519 Asia/Kathmandu Nepal
#
# +06
XX +2343+09025 Asia/Dhaka Russia; Kyrgyzstan; Bhutan; Bangladesh; Chagos
-# +06 until 2024-03-01; then +05
-XX +4315+07657 Asia/Almaty Kazakhstan (except western areas)
#
# +06:30
XX +1647+09610 Asia/Yangon Myanmar; Cocos
diff --git a/lib/simplejson/__init__.py b/lib/simplejson/__init__.py
index 2d1900d8..d3ff141d 100644
--- a/lib/simplejson/__init__.py
+++ b/lib/simplejson/__init__.py
@@ -118,7 +118,7 @@ Serializing multiple objects to JSON lines (newline-delimited JSON)::
"""
from __future__ import absolute_import
-__version__ = '3.19.2'
+__version__ = '3.19.3'
__all__ = [
'dump', 'dumps', 'load', 'loads',
'JSONDecoder', 'JSONDecodeError', 'JSONEncoder',
diff --git a/lib/tokenize_rt.py b/lib/tokenize_rt.py
index 9f12e01f..f909ead7 100644
--- a/lib/tokenize_rt.py
+++ b/lib/tokenize_rt.py
@@ -6,11 +6,11 @@ import keyword
import re
import sys
import tokenize
-from typing import Generator
-from typing import Iterable
+from collections.abc import Generator
+from collections.abc import Iterable
+from collections.abc import Sequence
+from re import Pattern
from typing import NamedTuple
-from typing import Pattern
-from typing import Sequence
# this is a performance hack. see https://bugs.python.org/issue43014
if ( # pragma: no branch
@@ -47,6 +47,16 @@ class Token(NamedTuple):
_string_re = re.compile('^([^\'"]*)(.*)$', re.DOTALL)
_escaped_nl_re = re.compile(r'\\(\n|\r\n|\r)')
+NAMED_UNICODE_RE = re.compile(r'(? str:
+ parts = NAMED_UNICODE_RE.split(s)
+ return ''.join(
+ part.replace('{', '{{').replace('}', '}}') if i % 2 == 0 else part
+ for i, part in enumerate(parts)
+ )
+
def _re_partition(regex: Pattern[str], s: str) -> tuple[str, str, str]:
match = regex.search(s)
@@ -101,8 +111,10 @@ def src_to_tokens(src: str) -> list[Token]:
tok_name = tokenize.tok_name[tok_type]
if tok_name == 'FSTRING_MIDDLE': # pragma: >=3.12 cover
- ecol += tok_text.count('{') + tok_text.count('}')
- tok_text = tok_text.replace('{', '{{').replace('}', '}}')
+ if '{' in tok_text or '}' in tok_text:
+ new_tok_text = curly_escape(tok_text)
+ ecol += len(new_tok_text) - len(tok_text)
+ tok_text = new_tok_text
tokens.append(Token(tok_name, tok_text, sline, end_offset))
last_line, last_col = eline, ecol
diff --git a/lib/tzdata/__init__.py b/lib/tzdata/__init__.py
index b319ed55..e558a8a5 100644
--- a/lib/tzdata/__init__.py
+++ b/lib/tzdata/__init__.py
@@ -1,6 +1,6 @@
# IANA versions like 2020a are not valid PEP 440 identifiers; the recommended
# way to translate the version is to use YYYY.n where `n` is a 0-based index.
-__version__ = "2024.1"
+__version__ = "2024.2"
# This exposes the original IANA version number.
-IANA_VERSION = "2024a"
+IANA_VERSION = "2024b"
diff --git a/lib/tzdata/zoneinfo/Africa/Blantyre b/lib/tzdata/zoneinfo/Africa/Blantyre
index 651e5cf6..581bb0e0 100644
Binary files a/lib/tzdata/zoneinfo/Africa/Blantyre and b/lib/tzdata/zoneinfo/Africa/Blantyre differ
diff --git a/lib/tzdata/zoneinfo/Africa/Bujumbura b/lib/tzdata/zoneinfo/Africa/Bujumbura
index 651e5cf6..581bb0e0 100644
Binary files a/lib/tzdata/zoneinfo/Africa/Bujumbura and b/lib/tzdata/zoneinfo/Africa/Bujumbura differ
diff --git a/lib/tzdata/zoneinfo/Africa/Gaborone b/lib/tzdata/zoneinfo/Africa/Gaborone
index 651e5cf6..581bb0e0 100644
Binary files a/lib/tzdata/zoneinfo/Africa/Gaborone and b/lib/tzdata/zoneinfo/Africa/Gaborone differ
diff --git a/lib/tzdata/zoneinfo/Africa/Harare b/lib/tzdata/zoneinfo/Africa/Harare
index 651e5cf6..581bb0e0 100644
Binary files a/lib/tzdata/zoneinfo/Africa/Harare and b/lib/tzdata/zoneinfo/Africa/Harare differ
diff --git a/lib/tzdata/zoneinfo/Africa/Kigali b/lib/tzdata/zoneinfo/Africa/Kigali
index 651e5cf6..581bb0e0 100644
Binary files a/lib/tzdata/zoneinfo/Africa/Kigali and b/lib/tzdata/zoneinfo/Africa/Kigali differ
diff --git a/lib/tzdata/zoneinfo/Africa/Lubumbashi b/lib/tzdata/zoneinfo/Africa/Lubumbashi
index 651e5cf6..581bb0e0 100644
Binary files a/lib/tzdata/zoneinfo/Africa/Lubumbashi and b/lib/tzdata/zoneinfo/Africa/Lubumbashi differ
diff --git a/lib/tzdata/zoneinfo/Africa/Lusaka b/lib/tzdata/zoneinfo/Africa/Lusaka
index 651e5cf6..581bb0e0 100644
Binary files a/lib/tzdata/zoneinfo/Africa/Lusaka and b/lib/tzdata/zoneinfo/Africa/Lusaka differ
diff --git a/lib/tzdata/zoneinfo/Africa/Maputo b/lib/tzdata/zoneinfo/Africa/Maputo
index 651e5cf6..581bb0e0 100644
Binary files a/lib/tzdata/zoneinfo/Africa/Maputo and b/lib/tzdata/zoneinfo/Africa/Maputo differ
diff --git a/lib/tzdata/zoneinfo/America/Bahia_Banderas b/lib/tzdata/zoneinfo/America/Bahia_Banderas
index 48faea2e..882400bd 100644
Binary files a/lib/tzdata/zoneinfo/America/Bahia_Banderas and b/lib/tzdata/zoneinfo/America/Bahia_Banderas differ
diff --git a/lib/tzdata/zoneinfo/America/Cancun b/lib/tzdata/zoneinfo/America/Cancun
index 640b259f..3110cdfd 100644
Binary files a/lib/tzdata/zoneinfo/America/Cancun and b/lib/tzdata/zoneinfo/America/Cancun differ
diff --git a/lib/tzdata/zoneinfo/America/Chihuahua b/lib/tzdata/zoneinfo/America/Chihuahua
index 5e0a54f0..f65bb1c9 100644
Binary files a/lib/tzdata/zoneinfo/America/Chihuahua and b/lib/tzdata/zoneinfo/America/Chihuahua differ
diff --git a/lib/tzdata/zoneinfo/America/Ciudad_Juarez b/lib/tzdata/zoneinfo/America/Ciudad_Juarez
index f636ee64..5f865ea8 100644
Binary files a/lib/tzdata/zoneinfo/America/Ciudad_Juarez and b/lib/tzdata/zoneinfo/America/Ciudad_Juarez differ
diff --git a/lib/tzdata/zoneinfo/America/Ensenada b/lib/tzdata/zoneinfo/America/Ensenada
index 42087af4..18d0d14a 100644
Binary files a/lib/tzdata/zoneinfo/America/Ensenada and b/lib/tzdata/zoneinfo/America/Ensenada differ
diff --git a/lib/tzdata/zoneinfo/America/Hermosillo b/lib/tzdata/zoneinfo/America/Hermosillo
index 5c92e296..ba7b1476 100644
Binary files a/lib/tzdata/zoneinfo/America/Hermosillo and b/lib/tzdata/zoneinfo/America/Hermosillo differ
diff --git a/lib/tzdata/zoneinfo/America/Mazatlan b/lib/tzdata/zoneinfo/America/Mazatlan
index 97d4d36c..5aa6039e 100644
Binary files a/lib/tzdata/zoneinfo/America/Mazatlan and b/lib/tzdata/zoneinfo/America/Mazatlan differ
diff --git a/lib/tzdata/zoneinfo/America/Merida b/lib/tzdata/zoneinfo/America/Merida
index e5de1131..e5c7d8cc 100644
Binary files a/lib/tzdata/zoneinfo/America/Merida and b/lib/tzdata/zoneinfo/America/Merida differ
diff --git a/lib/tzdata/zoneinfo/America/Mexico_City b/lib/tzdata/zoneinfo/America/Mexico_City
index 80a415c7..18112346 100644
Binary files a/lib/tzdata/zoneinfo/America/Mexico_City and b/lib/tzdata/zoneinfo/America/Mexico_City differ
diff --git a/lib/tzdata/zoneinfo/America/Monterrey b/lib/tzdata/zoneinfo/America/Monterrey
index a5822e2c..c1e05464 100644
Binary files a/lib/tzdata/zoneinfo/America/Monterrey and b/lib/tzdata/zoneinfo/America/Monterrey differ
diff --git a/lib/tzdata/zoneinfo/America/Ojinaga b/lib/tzdata/zoneinfo/America/Ojinaga
index f7e40c08..1dd08b1c 100644
Binary files a/lib/tzdata/zoneinfo/America/Ojinaga and b/lib/tzdata/zoneinfo/America/Ojinaga differ
diff --git a/lib/tzdata/zoneinfo/America/Santa_Isabel b/lib/tzdata/zoneinfo/America/Santa_Isabel
index 42087af4..18d0d14a 100644
Binary files a/lib/tzdata/zoneinfo/America/Santa_Isabel and b/lib/tzdata/zoneinfo/America/Santa_Isabel differ
diff --git a/lib/tzdata/zoneinfo/America/Tijuana b/lib/tzdata/zoneinfo/America/Tijuana
index 42087af4..18d0d14a 100644
Binary files a/lib/tzdata/zoneinfo/America/Tijuana and b/lib/tzdata/zoneinfo/America/Tijuana differ
diff --git a/lib/tzdata/zoneinfo/Asia/Choibalsan b/lib/tzdata/zoneinfo/Asia/Choibalsan
index 0a948c2e..6f5d3a15 100644
Binary files a/lib/tzdata/zoneinfo/Asia/Choibalsan and b/lib/tzdata/zoneinfo/Asia/Choibalsan differ
diff --git a/lib/tzdata/zoneinfo/Asia/Dili b/lib/tzdata/zoneinfo/Asia/Dili
index bb7be9f3..22e705ca 100644
Binary files a/lib/tzdata/zoneinfo/Asia/Dili and b/lib/tzdata/zoneinfo/Asia/Dili differ
diff --git a/lib/tzdata/zoneinfo/Atlantic/Azores b/lib/tzdata/zoneinfo/Atlantic/Azores
index e6e2616e..cda1c1d2 100644
Binary files a/lib/tzdata/zoneinfo/Atlantic/Azores and b/lib/tzdata/zoneinfo/Atlantic/Azores differ
diff --git a/lib/tzdata/zoneinfo/Atlantic/Madeira b/lib/tzdata/zoneinfo/Atlantic/Madeira
index cf965c3f..21e84571 100644
Binary files a/lib/tzdata/zoneinfo/Atlantic/Madeira and b/lib/tzdata/zoneinfo/Atlantic/Madeira differ
diff --git a/lib/tzdata/zoneinfo/CET b/lib/tzdata/zoneinfo/CET
index 546748d6..31973271 100644
Binary files a/lib/tzdata/zoneinfo/CET and b/lib/tzdata/zoneinfo/CET differ
diff --git a/lib/tzdata/zoneinfo/CST6CDT b/lib/tzdata/zoneinfo/CST6CDT
index d9315580..b0168806 100644
Binary files a/lib/tzdata/zoneinfo/CST6CDT and b/lib/tzdata/zoneinfo/CST6CDT differ
diff --git a/lib/tzdata/zoneinfo/EET b/lib/tzdata/zoneinfo/EET
index 378919ea..231bf9c3 100644
Binary files a/lib/tzdata/zoneinfo/EET and b/lib/tzdata/zoneinfo/EET differ
diff --git a/lib/tzdata/zoneinfo/EST b/lib/tzdata/zoneinfo/EST
index 3ae96911..9154643f 100644
Binary files a/lib/tzdata/zoneinfo/EST and b/lib/tzdata/zoneinfo/EST differ
diff --git a/lib/tzdata/zoneinfo/EST5EDT b/lib/tzdata/zoneinfo/EST5EDT
index 50c95e0c..2b6c2eea 100644
Binary files a/lib/tzdata/zoneinfo/EST5EDT and b/lib/tzdata/zoneinfo/EST5EDT differ
diff --git a/lib/tzdata/zoneinfo/Europe/Lisbon b/lib/tzdata/zoneinfo/Europe/Lisbon
index f0c70b69..7e9aae72 100644
Binary files a/lib/tzdata/zoneinfo/Europe/Lisbon and b/lib/tzdata/zoneinfo/Europe/Lisbon differ
diff --git a/lib/tzdata/zoneinfo/HST b/lib/tzdata/zoneinfo/HST
index 160a53e0..40e3d492 100644
Binary files a/lib/tzdata/zoneinfo/HST and b/lib/tzdata/zoneinfo/HST differ
diff --git a/lib/tzdata/zoneinfo/MET b/lib/tzdata/zoneinfo/MET
index 6f0558c3..31973271 100644
Binary files a/lib/tzdata/zoneinfo/MET and b/lib/tzdata/zoneinfo/MET differ
diff --git a/lib/tzdata/zoneinfo/MST b/lib/tzdata/zoneinfo/MST
index a0953d1e..c2bd2f94 100644
Binary files a/lib/tzdata/zoneinfo/MST and b/lib/tzdata/zoneinfo/MST differ
diff --git a/lib/tzdata/zoneinfo/MST7MDT b/lib/tzdata/zoneinfo/MST7MDT
index 137867c8..09e54e5c 100644
Binary files a/lib/tzdata/zoneinfo/MST7MDT and b/lib/tzdata/zoneinfo/MST7MDT differ
diff --git a/lib/tzdata/zoneinfo/Mexico/BajaNorte b/lib/tzdata/zoneinfo/Mexico/BajaNorte
index 42087af4..18d0d14a 100644
Binary files a/lib/tzdata/zoneinfo/Mexico/BajaNorte and b/lib/tzdata/zoneinfo/Mexico/BajaNorte differ
diff --git a/lib/tzdata/zoneinfo/Mexico/BajaSur b/lib/tzdata/zoneinfo/Mexico/BajaSur
index 97d4d36c..5aa6039e 100644
Binary files a/lib/tzdata/zoneinfo/Mexico/BajaSur and b/lib/tzdata/zoneinfo/Mexico/BajaSur differ
diff --git a/lib/tzdata/zoneinfo/Mexico/General b/lib/tzdata/zoneinfo/Mexico/General
index 80a415c7..18112346 100644
Binary files a/lib/tzdata/zoneinfo/Mexico/General and b/lib/tzdata/zoneinfo/Mexico/General differ
diff --git a/lib/tzdata/zoneinfo/PST8PDT b/lib/tzdata/zoneinfo/PST8PDT
index fde4833f..aaf07787 100644
Binary files a/lib/tzdata/zoneinfo/PST8PDT and b/lib/tzdata/zoneinfo/PST8PDT differ
diff --git a/lib/tzdata/zoneinfo/Portugal b/lib/tzdata/zoneinfo/Portugal
index f0c70b69..7e9aae72 100644
Binary files a/lib/tzdata/zoneinfo/Portugal and b/lib/tzdata/zoneinfo/Portugal differ
diff --git a/lib/tzdata/zoneinfo/WET b/lib/tzdata/zoneinfo/WET
index 423c6c20..7e9aae72 100644
Binary files a/lib/tzdata/zoneinfo/WET and b/lib/tzdata/zoneinfo/WET differ
diff --git a/lib/tzdata/zoneinfo/leapseconds b/lib/tzdata/zoneinfo/leapseconds
index ce150bfe..6c715cb2 100644
--- a/lib/tzdata/zoneinfo/leapseconds
+++ b/lib/tzdata/zoneinfo/leapseconds
@@ -69,11 +69,11 @@ Leap 2016 Dec 31 23:59:60 + S
# Any additional leap seconds will come after this.
# This Expires line is commented out for now,
# so that pre-2020a zic implementations do not reject this file.
-#Expires 2024 Dec 28 00:00:00
+#Expires 2025 Jun 28 00:00:00
# POSIX timestamps for the data in this file:
-#updated 1704708379 (2024-01-08 10:06:19 UTC)
-#expires 1735344000 (2024-12-28 00:00:00 UTC)
+#updated 1720104763 (2024-07-04 14:52:43 UTC)
+#expires 1751068800 (2025-06-28 00:00:00 UTC)
# Updated through IERS Bulletin C (https://hpiers.obspm.fr/iers/bul/bulc/bulletinc.dat)
-# File expires on 28 December 2024
+# File expires on 28 June 2025
diff --git a/lib/tzdata/zoneinfo/tzdata.zi b/lib/tzdata/zoneinfo/tzdata.zi
index be1c4085..62e78bb8 100644
--- a/lib/tzdata/zoneinfo/tzdata.zi
+++ b/lib/tzdata/zoneinfo/tzdata.zi
@@ -1,4 +1,4 @@
-# version 2024a
+# version 2024b
# This zic input file is in the public domain.
R d 1916 o - Jun 14 23s 1 S
R d 1916 1919 - O Su>=1 23s 0 -
@@ -1324,14 +1324,10 @@ R O 1961 1964 - May lastSu 1s 1 S
R O 1962 1964 - S lastSu 1s 0 -
R p 1916 o - Jun 17 23 1 S
R p 1916 o - N 1 1 0 -
-R p 1917 o - F 28 23s 1 S
-R p 1917 1921 - O 14 23s 0 -
-R p 1918 o - Mar 1 23s 1 S
-R p 1919 o - F 28 23s 1 S
-R p 1920 o - F 29 23s 1 S
-R p 1921 o - F 28 23s 1 S
+R p 1917 1921 - Mar 1 0 1 S
+R p 1917 1921 - O 14 24 0 -
R p 1924 o - Ap 16 23s 1 S
-R p 1924 o - O 14 23s 0 -
+R p 1924 o - O 4 23s 0 -
R p 1926 o - Ap 17 23s 1 S
R p 1926 1929 - O Sa>=1 23s 0 -
R p 1927 o - Ap 9 23s 1 S
@@ -1349,8 +1345,9 @@ R p 1938 o - Mar 26 23s 1 S
R p 1939 o - Ap 15 23s 1 S
R p 1939 o - N 18 23s 0 -
R p 1940 o - F 24 23s 1 S
-R p 1940 1941 - O 5 23s 0 -
+R p 1940 o - O 7 23s 0 -
R p 1941 o - Ap 5 23s 1 S
+R p 1941 o - O 5 23s 0 -
R p 1942 1945 - Mar Sa>=8 23s 1 S
R p 1942 o - Ap 25 22s 2 M
R p 1942 o - Au 15 22s 1 S
@@ -1360,16 +1357,16 @@ R p 1943 1945 - Au Sa>=25 22s 1 S
R p 1944 1945 - Ap Sa>=21 22s 2 M
R p 1946 o - Ap Sa>=1 23s 1 S
R p 1946 o - O Sa>=1 23s 0 -
-R p 1947 1965 - Ap Su>=1 2s 1 S
+R p 1947 1966 - Ap Su>=1 2s 1 S
R p 1947 1965 - O Su>=1 2s 0 -
-R p 1977 o - Mar 27 0s 1 S
-R p 1977 o - S 25 0s 0 -
-R p 1978 1979 - Ap Su>=1 0s 1 S
-R p 1978 o - O 1 0s 0 -
-R p 1979 1982 - S lastSu 1s 0 -
-R p 1980 o - Mar lastSu 0s 1 S
-R p 1981 1982 - Mar lastSu 1s 1 S
-R p 1983 o - Mar lastSu 2s 1 S
+R p 1976 o - S lastSu 1 0 -
+R p 1977 o - Mar lastSu 0s 1 S
+R p 1977 o - S lastSu 0s 0 -
+R p 1978 1980 - Ap Su>=1 1s 1 S
+R p 1978 o - O 1 1s 0 -
+R p 1979 1980 - S lastSu 1s 0 -
+R p 1981 1986 - Mar lastSu 0s 1 S
+R p 1981 1985 - S lastSu 0s 0 -
R z 1932 o - May 21 0s 1 S
R z 1932 1939 - O Su>=1 0s 0 -
R z 1933 1939 - Ap Su>=2 0s 1 S
@@ -1728,7 +1725,7 @@ R Y 1972 2006 - O lastSu 2 0 S
R Y 1987 2006 - Ap Su>=1 2 1 D
R Yu 1965 o - Ap lastSu 0 2 DD
R Yu 1965 o - O lastSu 2 0 S
-R m 1931 o - May 1 23 1 D
+R m 1931 o - April 30 0 1 D
R m 1931 o - O 1 0 0 S
R m 1939 o - F 5 0 1 D
R m 1939 o - Jun 25 0 0 S
@@ -2096,15 +2093,15 @@ Z Africa/Algiers 0:12:12 - LMT 1891 Mar 16
0 d WE%sT 1981 May
1 - CET
Z Africa/Bissau -1:2:20 - LMT 1912 Ja 1 1u
--1 - -01 1975
+-1 - %z 1975
0 - GMT
Z Africa/Cairo 2:5:9 - LMT 1900 O
2 K EE%sT
Z Africa/Casablanca -0:30:20 - LMT 1913 O 26
-0 M +00/+01 1984 Mar 16
-1 - +01 1986
-0 M +00/+01 2018 O 28 3
-1 M +01/+00
+0 M %z 1984 Mar 16
+1 - %z 1986
+0 M %z 2018 O 28 3
+1 M %z
Z Africa/Ceuta -0:21:16 - LMT 1901 Ja 1 0u
0 - WET 1918 May 6 23
0 1 WEST 1918 O 7 23
@@ -2115,9 +2112,9 @@ Z Africa/Ceuta -0:21:16 - LMT 1901 Ja 1 0u
1 - CET 1986
1 E CE%sT
Z Africa/El_Aaiun -0:52:48 - LMT 1934
--1 - -01 1976 Ap 14
-0 M +00/+01 2018 O 28 3
-1 M +01/+00
+-1 - %z 1976 Ap 14
+0 M %z 2018 O 28 3
+1 M %z
Z Africa/Johannesburg 1:52 - LMT 1892 F 8
1:30 - SAST 1903 Mar
2 SA SAST
@@ -2132,19 +2129,19 @@ Z Africa/Khartoum 2:10:8 - LMT 1931
Z Africa/Lagos 0:13:35 - LMT 1905 Jul
0 - GMT 1908 Jul
0:13:35 - LMT 1914
-0:30 - +0030 1919 S
+0:30 - %z 1919 S
1 - WAT
-Z Africa/Maputo 2:10:20 - LMT 1903 Mar
+Z Africa/Maputo 2:10:18 - LMT 1909
2 - CAT
Z Africa/Monrovia -0:43:8 - LMT 1882
-0:43:8 - MMT 1919 Mar
-0:44:30 - MMT 1972 Ja 7
0 - GMT
Z Africa/Nairobi 2:27:16 - LMT 1908 May
-2:30 - +0230 1928 Jun 30 24
+2:30 - %z 1928 Jun 30 24
3 - EAT 1930 Ja 4 24
-2:30 - +0230 1936 D 31 24
-2:45 - +0245 1942 Jul 31 24
+2:30 - %z 1936 D 31 24
+2:45 - %z 1942 Jul 31 24
3 - EAT
Z Africa/Ndjamena 1:0:12 - LMT 1912
1 - WAT 1979 O 14
@@ -2168,7 +2165,7 @@ Z Africa/Tunis 0:40:44 - LMT 1881 May 12
0:9:21 - PMT 1911 Mar 11
1 n CE%sT
Z Africa/Windhoek 1:8:24 - LMT 1892 F 8
-1:30 - +0130 1903 Mar
+1:30 - %z 1903 Mar
2 - SAST 1942 S 20 2
2 1 SAST 1943 Mar 21 2
2 - SAST 1990 Mar 21
@@ -2191,167 +2188,166 @@ Z America/Anchorage 14:0:24 - LMT 1867 O 19 14:31:37
-9 u Y%sT 1983 N 30
-9 u AK%sT
Z America/Araguaina -3:12:48 - LMT 1914
--3 B -03/-02 1990 S 17
--3 - -03 1995 S 14
--3 B -03/-02 2003 S 24
--3 - -03 2012 O 21
--3 B -03/-02 2013 S
--3 - -03
+-3 B %z 1990 S 17
+-3 - %z 1995 S 14
+-3 B %z 2003 S 24
+-3 - %z 2012 O 21
+-3 B %z 2013 S
+-3 - %z
Z America/Argentina/Buenos_Aires -3:53:48 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 A -03/-02
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 A %z
Z America/Argentina/Catamarca -4:23:8 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1991 Mar 3
--4 - -04 1991 O 20
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 - -03 2004 Jun
--4 - -04 2004 Jun 20
--3 A -03/-02 2008 O 18
--3 - -03
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1991 Mar 3
+-4 - %z 1991 O 20
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 Jun
+-4 - %z 2004 Jun 20
+-3 A %z 2008 O 18
+-3 - %z
Z America/Argentina/Cordoba -4:16:48 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1991 Mar 3
--4 - -04 1991 O 20
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 A -03/-02
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1991 Mar 3
+-4 - %z 1991 O 20
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 A %z
Z America/Argentina/Jujuy -4:21:12 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1990 Mar 4
--4 - -04 1990 O 28
--4 1 -03 1991 Mar 17
--4 - -04 1991 O 6
--3 1 -02 1992
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 A -03/-02 2008 O 18
--3 - -03
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1990 Mar 4
+-4 - %z 1990 O 28
+-4 1 %z 1991 Mar 17
+-4 - %z 1991 O 6
+-3 1 %z 1992
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 A %z 2008 O 18
+-3 - %z
Z America/Argentina/La_Rioja -4:27:24 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1991 Mar
--4 - -04 1991 May 7
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 - -03 2004 Jun
--4 - -04 2004 Jun 20
--3 A -03/-02 2008 O 18
--3 - -03
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1991 Mar
+-4 - %z 1991 May 7
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 Jun
+-4 - %z 2004 Jun 20
+-3 A %z 2008 O 18
+-3 - %z
Z America/Argentina/Mendoza -4:35:16 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1990 Mar 4
--4 - -04 1990 O 15
--4 1 -03 1991 Mar
--4 - -04 1991 O 15
--4 1 -03 1992 Mar
--4 - -04 1992 O 18
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 - -03 2004 May 23
--4 - -04 2004 S 26
--3 A -03/-02 2008 O 18
--3 - -03
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1990 Mar 4
+-4 - %z 1990 O 15
+-4 1 %z 1991 Mar
+-4 - %z 1991 O 15
+-4 1 %z 1992 Mar
+-4 - %z 1992 O 18
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 May 23
+-4 - %z 2004 S 26
+-3 A %z 2008 O 18
+-3 - %z
Z America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 - -03 2004 Jun
--4 - -04 2004 Jun 20
--3 A -03/-02 2008 O 18
--3 - -03
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 Jun
+-4 - %z 2004 Jun 20
+-3 A %z 2008 O 18
+-3 - %z
Z America/Argentina/Salta -4:21:40 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1991 Mar 3
--4 - -04 1991 O 20
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 A -03/-02 2008 O 18
--3 - -03
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1991 Mar 3
+-4 - %z 1991 O 20
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 A %z 2008 O 18
+-3 - %z
Z America/Argentina/San_Juan -4:34:4 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1991 Mar
--4 - -04 1991 May 7
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 - -03 2004 May 31
--4 - -04 2004 Jul 25
--3 A -03/-02 2008 O 18
--3 - -03
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1991 Mar
+-4 - %z 1991 May 7
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 May 31
+-4 - %z 2004 Jul 25
+-3 A %z 2008 O 18
+-3 - %z
Z America/Argentina/San_Luis -4:25:24 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1990
--3 1 -02 1990 Mar 14
--4 - -04 1990 O 15
--4 1 -03 1991 Mar
--4 - -04 1991 Jun
--3 - -03 1999 O 3
--4 1 -03 2000 Mar 3
--3 - -03 2004 May 31
--4 - -04 2004 Jul 25
--3 A -03/-02 2008 Ja 21
--4 Sa -04/-03 2009 O 11
--3 - -03
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1990
+-3 1 %z 1990 Mar 14
+-4 - %z 1990 O 15
+-4 1 %z 1991 Mar
+-4 - %z 1991 Jun
+-3 - %z 1999 O 3
+-4 1 %z 2000 Mar 3
+-3 - %z 2004 May 31
+-4 - %z 2004 Jul 25
+-3 A %z 2008 Ja 21
+-4 Sa %z 2009 O 11
+-3 - %z
Z America/Argentina/Tucuman -4:20:52 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1991 Mar 3
--4 - -04 1991 O 20
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 - -03 2004 Jun
--4 - -04 2004 Jun 13
--3 A -03/-02
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1991 Mar 3
+-4 - %z 1991 O 20
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 Jun
+-4 - %z 2004 Jun 13
+-3 A %z
Z America/Argentina/Ushuaia -4:33:12 - LMT 1894 O 31
-4:16:48 - CMT 1920 May
--4 - -04 1930 D
--4 A -04/-03 1969 O 5
--3 A -03/-02 1999 O 3
--4 A -04/-03 2000 Mar 3
--3 - -03 2004 May 30
--4 - -04 2004 Jun 20
--3 A -03/-02 2008 O 18
--3 - -03
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 May 30
+-4 - %z 2004 Jun 20
+-3 A %z 2008 O 18
+-3 - %z
Z America/Asuncion -3:50:40 - LMT 1890
-3:50:40 - AMT 1931 O 10
--4 - -04 1972 O
--3 - -03 1974 Ap
--4 y -04/-03
+-4 - %z 1972 O
+-3 - %z 1974 Ap
+-4 y %z
Z America/Bahia -2:34:4 - LMT 1914
--3 B -03/-02 2003 S 24
--3 - -03 2011 O 16
--3 B -03/-02 2012 O 21
--3 - -03
+-3 B %z 2003 S 24
+-3 - %z 2011 O 16
+-3 B %z 2012 O 21
+-3 - %z
Z America/Bahia_Banderas -7:1 - LMT 1922 Ja 1 7u
--7 - MST 1927 Jun 10 23
+-7 - MST 1927 Jun 10
-6 - CST 1930 N 15
-7 m M%sT 1932 Ap
-6 - CST 1942 Ap 24
--7 - MST 1949 Ja 14
--8 - PST 1970
+-7 - MST 1970
-7 m M%sT 2010 Ap 4 2
-6 m C%sT
Z America/Barbados -3:58:29 - LMT 1911 Au 28
@@ -2359,18 +2355,18 @@ Z America/Barbados -3:58:29 - LMT 1911 Au 28
-4 BB AST/-0330 1945
-4 BB A%sT
Z America/Belem -3:13:56 - LMT 1914
--3 B -03/-02 1988 S 12
--3 - -03
+-3 B %z 1988 S 12
+-3 - %z
Z America/Belize -5:52:48 - LMT 1912 Ap
-6 BZ %s
Z America/Boa_Vista -4:2:40 - LMT 1914
--4 B -04/-03 1988 S 12
--4 - -04 1999 S 30
--4 B -04/-03 2000 O 15
--4 - -04
+-4 B %z 1988 S 12
+-4 - %z 1999 S 30
+-4 B %z 2000 O 15
+-4 - %z
Z America/Bogota -4:56:16 - LMT 1884 Mar 13
-4:56:16 - BMT 1914 N 23
--5 CO -05/-04
+-5 CO %z
Z America/Boise -7:44:49 - LMT 1883 N 18 20u
-8 u P%sT 1923 May 13 2
-7 u M%sT 1974
@@ -2383,21 +2379,23 @@ Z America/Cambridge_Bay 0 - -00 1920
-6 - CST 2001 Ap 1 3
-7 C M%sT
Z America/Campo_Grande -3:38:28 - LMT 1914
--4 B -04/-03
+-4 B %z
Z America/Cancun -5:47:4 - LMT 1922 Ja 1 6u
--6 - CST 1981 D 23
+-6 - CST 1981 D 26 2
+-5 - EST 1983 Ja 4
+-6 m C%sT 1997 O 26 2
-5 m E%sT 1998 Au 2 2
-6 m C%sT 2015 F 1 2
-5 - EST
Z America/Caracas -4:27:44 - LMT 1890
-4:27:40 - CMT 1912 F 12
--4:30 - -0430 1965
--4 - -04 2007 D 9 3
--4:30 - -0430 2016 May 1 2:30
--4 - -04
+-4:30 - %z 1965
+-4 - %z 2007 D 9 3
+-4:30 - %z 2016 May 1 2:30
+-4 - %z
Z America/Cayenne -3:29:20 - LMT 1911 Jul
--4 - -04 1967 O
--3 - -03
+-4 - %z 1967 O
+-3 - %z
Z America/Chicago -5:50:36 - LMT 1883 N 18 18u
-6 u C%sT 1920
-6 Ch C%sT 1936 Mar 1 2
@@ -2407,7 +2405,7 @@ Z America/Chicago -5:50:36 - LMT 1883 N 18 18u
-6 Ch C%sT 1967
-6 u C%sT
Z America/Chihuahua -7:4:20 - LMT 1922 Ja 1 7u
--7 - MST 1927 Jun 10 23
+-7 - MST 1927 Jun 10
-6 - CST 1930 N 15
-7 m M%sT 1932 Ap
-6 - CST 1996
@@ -2416,7 +2414,7 @@ Z America/Chihuahua -7:4:20 - LMT 1922 Ja 1 7u
-7 m M%sT 2022 O 30 2
-6 - CST
Z America/Ciudad_Juarez -7:5:56 - LMT 1922 Ja 1 7u
--7 - MST 1927 Jun 10 23
+-7 - MST 1927 Jun 10
-6 - CST 1930 N 15
-7 m M%sT 1932 Ap
-6 - CST 1996
@@ -2430,12 +2428,12 @@ Z America/Costa_Rica -5:36:13 - LMT 1890
-5:36:13 - SJMT 1921 Ja 15
-6 CR C%sT
Z America/Cuiaba -3:44:20 - LMT 1914
--4 B -04/-03 2003 S 24
--4 - -04 2004 O
--4 B -04/-03
+-4 B %z 2003 S 24
+-4 - %z 2004 O
+-4 B %z
Z America/Danmarkshavn -1:14:40 - LMT 1916 Jul 28
--3 - -03 1980 Ap 6 2
--3 E -03/-02 1996
+-3 - %z 1980 Ap 6 2
+-3 E %z 1996
0 - GMT
Z America/Dawson -9:17:40 - LMT 1900 Au 20
-9 Y Y%sT 1965
@@ -2467,12 +2465,12 @@ Z America/Edmonton -7:33:52 - LMT 1906 S
-7 Ed M%sT 1987
-7 C M%sT
Z America/Eirunepe -4:39:28 - LMT 1914
--5 B -05/-04 1988 S 12
--5 - -05 1993 S 28
--5 B -05/-04 1994 S 22
--5 - -05 2008 Jun 24
--4 - -04 2013 N 10
--5 - -05
+-5 B %z 1988 S 12
+-5 - %z 1993 S 28
+-5 B %z 1994 S 22
+-5 - %z 2008 Jun 24
+-4 - %z 2013 N 10
+-5 - %z
Z America/El_Salvador -5:56:48 - LMT 1921
-6 SV C%sT
Z America/Fort_Nelson -8:10:47 - LMT 1884
@@ -2482,12 +2480,12 @@ Z America/Fort_Nelson -8:10:47 - LMT 1884
-8 C P%sT 2015 Mar 8 2
-7 - MST
Z America/Fortaleza -2:34 - LMT 1914
--3 B -03/-02 1990 S 17
--3 - -03 1999 S 30
--3 B -03/-02 2000 O 22
--3 - -03 2001 S 13
--3 B -03/-02 2002 O
--3 - -03
+-3 B %z 1990 S 17
+-3 - %z 1999 S 30
+-3 B %z 2000 O 22
+-3 - %z 2001 S 13
+-3 B %z 2002 O
+-3 - %z
Z America/Glace_Bay -3:59:48 - LMT 1902 Jun 15
-4 C A%sT 1953
-4 H A%sT 1954
@@ -2514,12 +2512,12 @@ Z America/Guatemala -6:2:4 - LMT 1918 O 5
-6 GT C%sT
Z America/Guayaquil -5:19:20 - LMT 1890
-5:14 - QMT 1931
--5 EC -05/-04
+-5 EC %z
Z America/Guyana -3:52:39 - LMT 1911 Au
--4 - -04 1915 Mar
--3:45 - -0345 1975 Au
--3 - -03 1992 Mar 29 1
--4 - -04
+-4 - %z 1915 Mar
+-3:45 - %z 1975 Au
+-3 - %z 1992 Mar 29 1
+-4 - %z
Z America/Halifax -4:14:24 - LMT 1902 Jun 15
-4 H A%sT 1918
-4 C A%sT 1919
@@ -2531,12 +2529,11 @@ Z America/Havana -5:29:28 - LMT 1890
-5:29:36 - HMT 1925 Jul 19 12
-5 Q C%sT
Z America/Hermosillo -7:23:52 - LMT 1922 Ja 1 7u
--7 - MST 1927 Jun 10 23
+-7 - MST 1927 Jun 10
-6 - CST 1930 N 15
-7 m M%sT 1932 Ap
-6 - CST 1942 Ap 24
--7 - MST 1949 Ja 14
--8 - PST 1970
+-7 - MST 1996
-7 m M%sT 1999
-7 - MST
Z America/Indiana/Indianapolis -5:44:38 - LMT 1883 N 18 18u
@@ -2644,23 +2641,23 @@ Z America/Kentucky/Monticello -5:39:24 - LMT 1883 N 18 18u
Z America/La_Paz -4:32:36 - LMT 1890
-4:32:36 - CMT 1931 O 15
-4:32:36 1 BST 1932 Mar 21
--4 - -04
+-4 - %z
Z America/Lima -5:8:12 - LMT 1890
-5:8:36 - LMT 1908 Jul 28
--5 PE -05/-04
+-5 PE %z
Z America/Los_Angeles -7:52:58 - LMT 1883 N 18 20u
-8 u P%sT 1946
-8 CA P%sT 1967
-8 u P%sT
Z America/Maceio -2:22:52 - LMT 1914
--3 B -03/-02 1990 S 17
--3 - -03 1995 O 13
--3 B -03/-02 1996 S 4
--3 - -03 1999 S 30
--3 B -03/-02 2000 O 22
--3 - -03 2001 S 13
--3 B -03/-02 2002 O
--3 - -03
+-3 B %z 1990 S 17
+-3 - %z 1995 O 13
+-3 B %z 1996 S 4
+-3 - %z 1999 S 30
+-3 B %z 2000 O 22
+-3 - %z 2001 S 13
+-3 B %z 2002 O
+-3 - %z
Z America/Managua -5:45:8 - LMT 1890
-5:45:12 - MMT 1934 Jun 23
-6 - CST 1973 May
@@ -2671,10 +2668,10 @@ Z America/Managua -5:45:8 - LMT 1890
-5 - EST 1997
-6 NI C%sT
Z America/Manaus -4:0:4 - LMT 1914
--4 B -04/-03 1988 S 12
--4 - -04 1993 S 28
--4 B -04/-03 1994 S 22
--4 - -04
+-4 B %z 1988 S 12
+-4 - %z 1993 S 28
+-4 B %z 1994 S 22
+-4 - %z
Z America/Martinique -4:4:20 - LMT 1890
-4:4:20 - FFMT 1911 May
-4 - AST 1980 Ap 6
@@ -2686,12 +2683,11 @@ Z America/Matamoros -6:30 - LMT 1922 Ja 1 6u
-6 m C%sT 2010
-6 u C%sT
Z America/Mazatlan -7:5:40 - LMT 1922 Ja 1 7u
--7 - MST 1927 Jun 10 23
+-7 - MST 1927 Jun 10
-6 - CST 1930 N 15
-7 m M%sT 1932 Ap
-6 - CST 1942 Ap 24
--7 - MST 1949 Ja 14
--8 - PST 1970
+-7 - MST 1970
-7 m M%sT
Z America/Menominee -5:50:27 - LMT 1885 S 18 12
-6 u C%sT 1946
@@ -2699,8 +2695,8 @@ Z America/Menominee -5:50:27 - LMT 1885 S 18 12
-5 - EST 1973 Ap 29 2
-6 u C%sT
Z America/Merida -5:58:28 - LMT 1922 Ja 1 6u
--6 - CST 1981 D 23
--5 - EST 1982 D 2
+-6 - CST 1981 D 26 2
+-5 - EST 1982 N 2 2
-6 m C%sT
Z America/Metlakatla 15:13:42 - LMT 1867 O 19 15:44:55
-8:46:18 - LMT 1900 Au 20 12
@@ -2713,7 +2709,7 @@ Z America/Metlakatla 15:13:42 - LMT 1867 O 19 15:44:55
-8 - PST 2019 Ja 20 2
-9 u AK%sT
Z America/Mexico_City -6:36:36 - LMT 1922 Ja 1 7u
--7 - MST 1927 Jun 10 23
+-7 - MST 1927 Jun 10
-6 - CST 1930 N 15
-7 m M%sT 1932 Ap
-6 m C%sT 2001 S 30 2
@@ -2721,8 +2717,8 @@ Z America/Mexico_City -6:36:36 - LMT 1922 Ja 1 7u
-6 m C%sT
Z America/Miquelon -3:44:40 - LMT 1911 Jun 15
-4 - AST 1980 May
--3 - -03 1987
--3 C -03/-02
+-3 - %z 1987
+-3 C %z
Z America/Moncton -4:19:8 - LMT 1883 D 9
-5 - EST 1902 Jun 15
-4 C A%sT 1933
@@ -2733,20 +2729,23 @@ Z America/Moncton -4:19:8 - LMT 1883 D 9
-4 o A%sT 2007
-4 C A%sT
Z America/Monterrey -6:41:16 - LMT 1922 Ja 1 6u
+-7 - MST 1927 Jun 10
+-6 - CST 1930 N 15
+-7 m M%sT 1932 Ap
-6 - CST 1988
-6 u C%sT 1989
-6 m C%sT
Z America/Montevideo -3:44:51 - LMT 1908 Jun 10
-3:44:51 - MMT 1920 May
--4 - -04 1923 O
--3:30 U -0330/-03 1942 D 14
--3 U -03/-0230 1960
--3 U -03/-02 1968
--3 U -03/-0230 1970
--3 U -03/-02 1974
--3 U -03/-0130 1974 Mar 10
--3 U -03/-0230 1974 D 22
--3 U -03/-02
+-4 - %z 1923 O
+-3:30 U %z 1942 D 14
+-3 U %z 1960
+-3 U %z 1968
+-3 U %z 1970
+-3 U %z 1974
+-3 U %z 1974 Mar 10
+-3 U %z 1974 D 22
+-3 U %z
Z America/New_York -4:56:2 - LMT 1883 N 18 17u
-5 u E%sT 1920
-5 NY E%sT 1942
@@ -2763,12 +2762,12 @@ Z America/Nome 12:58:22 - LMT 1867 O 19 13:29:35
-9 u Y%sT 1983 N 30
-9 u AK%sT
Z America/Noronha -2:9:40 - LMT 1914
--2 B -02/-01 1990 S 17
--2 - -02 1999 S 30
--2 B -02/-01 2000 O 15
--2 - -02 2001 S 13
--2 B -02/-01 2002 O
--2 - -02
+-2 B %z 1990 S 17
+-2 - %z 1999 S 30
+-2 B %z 2000 O 15
+-2 - %z 2001 S 13
+-2 B %z 2002 O
+-2 - %z
Z America/North_Dakota/Beulah -6:47:7 - LMT 1883 N 18 19u
-7 u M%sT 2010 N 7 2
-6 u C%sT
@@ -2779,12 +2778,12 @@ Z America/North_Dakota/New_Salem -6:45:39 - LMT 1883 N 18 19u
-7 u M%sT 2003 O 26 2
-6 u C%sT
Z America/Nuuk -3:26:56 - LMT 1916 Jul 28
--3 - -03 1980 Ap 6 2
--3 E -03/-02 2023 Mar 26 1u
--2 - -02 2023 O 29 1u
--2 E -02/-01
+-3 - %z 1980 Ap 6 2
+-3 E %z 2023 Mar 26 1u
+-2 - %z 2023 O 29 1u
+-2 E %z
Z America/Ojinaga -6:57:40 - LMT 1922 Ja 1 7u
--7 - MST 1927 Jun 10 23
+-7 - MST 1927 Jun 10
-6 - CST 1930 N 15
-7 m M%sT 1932 Ap
-6 - CST 1996
@@ -2800,8 +2799,8 @@ Z America/Panama -5:18:8 - LMT 1890
Z America/Paramaribo -3:40:40 - LMT 1911
-3:40:52 - PMT 1935
-3:40:36 - PMT 1945 O
--3:30 - -0330 1984 O
--3 - -03
+-3:30 - %z 1984 O
+-3 - %z
Z America/Phoenix -7:28:18 - LMT 1883 N 18 19u
-7 u M%sT 1944 Ja 1 0:1
-7 - MST 1944 Ap 1 0:1
@@ -2813,37 +2812,37 @@ Z America/Port-au-Prince -4:49:20 - LMT 1890
-4:49 - PPMT 1917 Ja 24 12
-5 HT E%sT
Z America/Porto_Velho -4:15:36 - LMT 1914
--4 B -04/-03 1988 S 12
--4 - -04
+-4 B %z 1988 S 12
+-4 - %z
Z America/Puerto_Rico -4:24:25 - LMT 1899 Mar 28 12
-4 - AST 1942 May 3
-4 u A%sT 1946
-4 - AST
Z America/Punta_Arenas -4:43:40 - LMT 1890
-4:42:45 - SMT 1910 Ja 10
--5 - -05 1916 Jul
+-5 - %z 1916 Jul
-4:42:45 - SMT 1918 S 10
--4 - -04 1919 Jul
+-4 - %z 1919 Jul
-4:42:45 - SMT 1927 S
--5 x -05/-04 1932 S
--4 - -04 1942 Jun
--5 - -05 1942 Au
--4 - -04 1946 Au 28 24
--5 1 -04 1947 Mar 31 24
--5 - -05 1947 May 21 23
--4 x -04/-03 2016 D 4
--3 - -03
+-5 x %z 1932 S
+-4 - %z 1942 Jun
+-5 - %z 1942 Au
+-4 - %z 1946 Au 28 24
+-5 1 %z 1947 Mar 31 24
+-5 - %z 1947 May 21 23
+-4 x %z 2016 D 4
+-3 - %z
Z America/Rankin_Inlet 0 - -00 1957
-6 Y C%sT 2000 O 29 2
-5 - EST 2001 Ap 1 3
-6 C C%sT
Z America/Recife -2:19:36 - LMT 1914
--3 B -03/-02 1990 S 17
--3 - -03 1999 S 30
--3 B -03/-02 2000 O 15
--3 - -03 2001 S 13
--3 B -03/-02 2002 O
--3 - -03
+-3 B %z 1990 S 17
+-3 - %z 1999 S 30
+-3 B %z 2000 O 15
+-3 - %z 2001 S 13
+-3 B %z 2002 O
+-3 - %z
Z America/Regina -6:58:36 - LMT 1905 S
-7 r M%sT 1960 Ap lastSu 2
-6 - CST
@@ -2854,28 +2853,28 @@ Z America/Resolute 0 - -00 1947 Au 31
-5 - EST 2007 Mar 11 3
-6 C C%sT
Z America/Rio_Branco -4:31:12 - LMT 1914
--5 B -05/-04 1988 S 12
--5 - -05 2008 Jun 24
--4 - -04 2013 N 10
--5 - -05
+-5 B %z 1988 S 12
+-5 - %z 2008 Jun 24
+-4 - %z 2013 N 10
+-5 - %z
Z America/Santarem -3:38:48 - LMT 1914
--4 B -04/-03 1988 S 12
--4 - -04 2008 Jun 24
--3 - -03
+-4 B %z 1988 S 12
+-4 - %z 2008 Jun 24
+-3 - %z
Z America/Santiago -4:42:45 - LMT 1890
-4:42:45 - SMT 1910 Ja 10
--5 - -05 1916 Jul
+-5 - %z 1916 Jul
-4:42:45 - SMT 1918 S 10
--4 - -04 1919 Jul
+-4 - %z 1919 Jul
-4:42:45 - SMT 1927 S
--5 x -05/-04 1932 S
--4 - -04 1942 Jun
--5 - -05 1942 Au
--4 - -04 1946 Jul 14 24
--4 1 -03 1946 Au 28 24
--5 1 -04 1947 Mar 31 24
--5 - -05 1947 May 21 23
--4 x -04/-03
+-5 x %z 1932 S
+-4 - %z 1942 Jun
+-5 - %z 1942 Au
+-4 - %z 1946 Jul 14 24
+-4 1 %z 1946 Au 28 24
+-5 1 %z 1947 Mar 31 24
+-5 - %z 1947 May 21 23
+-4 x %z
Z America/Santo_Domingo -4:39:36 - LMT 1890
-4:40 - SDMT 1933 Ap 1 12
-5 DO %s 1974 O 27
@@ -2883,14 +2882,14 @@ Z America/Santo_Domingo -4:39:36 - LMT 1890
-5 u E%sT 2000 D 3 1
-4 - AST
Z America/Sao_Paulo -3:6:28 - LMT 1914
--3 B -03/-02 1963 O 23
--3 1 -02 1964
--3 B -03/-02
+-3 B %z 1963 O 23
+-3 1 %z 1964
+-3 B %z
Z America/Scoresbysund -1:27:52 - LMT 1916 Jul 28
--2 - -02 1980 Ap 6 2
--2 c -02/-01 1981 Mar 29
--1 E -01/+00 2024 Mar 31
--2 E -02/-01
+-2 - %z 1980 Ap 6 2
+-2 c %z 1981 Mar 29
+-1 E %z 2024 Mar 31
+-2 E %z
Z America/Sitka 14:58:47 - LMT 1867 O 19 15:30
-9:1:13 - LMT 1900 Au 20 12
-8 - PST 1942
@@ -2918,15 +2917,21 @@ Z America/Thule -4:35:8 - LMT 1916 Jul 28
-4 Th A%sT
Z America/Tijuana -7:48:4 - LMT 1922 Ja 1 7u
-7 - MST 1924
--8 - PST 1927 Jun 10 23
+-8 - PST 1927 Jun 10
-7 - MST 1930 N 15
-8 - PST 1931 Ap
-8 1 PDT 1931 S 30
-8 - PST 1942 Ap 24
-8 1 PWT 1945 Au 14 23u
--8 1 PPT 1945 N 12
+-8 1 PPT 1945 N 15
-8 - PST 1948 Ap 5
-8 1 PDT 1949 Ja 14
+-8 - PST 1950 May
+-8 1 PDT 1950 S 24
+-8 - PST 1951 Ap 29 2
+-8 1 PDT 1951 S 30 2
+-8 - PST 1952 Ap 27 2
+-8 1 PDT 1952 S 28 2
-8 - PST 1954
-8 CA P%sT 1961
-8 - PST 1976
@@ -2961,31 +2966,31 @@ Z America/Yakutat 14:41:5 - LMT 1867 O 19 15:12:18
-9 u Y%sT 1983 N 30
-9 u AK%sT
Z Antarctica/Casey 0 - -00 1969
-8 - +08 2009 O 18 2
-11 - +11 2010 Mar 5 2
-8 - +08 2011 O 28 2
-11 - +11 2012 F 21 17u
-8 - +08 2016 O 22
-11 - +11 2018 Mar 11 4
-8 - +08 2018 O 7 4
-11 - +11 2019 Mar 17 3
-8 - +08 2019 O 4 3
-11 - +11 2020 Mar 8 3
-8 - +08 2020 O 4 0:1
-11 - +11 2021 Mar 14
-8 - +08 2021 O 3 0:1
-11 - +11 2022 Mar 13
-8 - +08 2022 O 2 0:1
-11 - +11 2023 Mar 9 3
-8 - +08
+8 - %z 2009 O 18 2
+11 - %z 2010 Mar 5 2
+8 - %z 2011 O 28 2
+11 - %z 2012 F 21 17u
+8 - %z 2016 O 22
+11 - %z 2018 Mar 11 4
+8 - %z 2018 O 7 4
+11 - %z 2019 Mar 17 3
+8 - %z 2019 O 4 3
+11 - %z 2020 Mar 8 3
+8 - %z 2020 O 4 0:1
+11 - %z 2021 Mar 14
+8 - %z 2021 O 3 0:1
+11 - %z 2022 Mar 13
+8 - %z 2022 O 2 0:1
+11 - %z 2023 Mar 9 3
+8 - %z
Z Antarctica/Davis 0 - -00 1957 Ja 13
-7 - +07 1964 N
+7 - %z 1964 N
0 - -00 1969 F
-7 - +07 2009 O 18 2
-5 - +05 2010 Mar 10 20u
-7 - +07 2011 O 28 2
-5 - +05 2012 F 21 20u
-7 - +07
+7 - %z 2009 O 18 2
+5 - %z 2010 Mar 10 20u
+7 - %z 2011 O 28 2
+5 - %z 2012 F 21 20u
+7 - %z
Z Antarctica/Macquarie 0 - -00 1899 N
10 - AEST 1916 O 1 2
10 1 AEDT 1917 F
@@ -2996,151 +3001,146 @@ Z Antarctica/Macquarie 0 - -00 1899 N
10 1 AEDT 2011
10 AT AE%sT
Z Antarctica/Mawson 0 - -00 1954 F 13
-6 - +06 2009 O 18 2
-5 - +05
+6 - %z 2009 O 18 2
+5 - %z
Z Antarctica/Palmer 0 - -00 1965
--4 A -04/-03 1969 O 5
--3 A -03/-02 1982 May
--4 x -04/-03 2016 D 4
--3 - -03
+-4 A %z 1969 O 5
+-3 A %z 1982 May
+-4 x %z 2016 D 4
+-3 - %z
Z Antarctica/Rothera 0 - -00 1976 D
--3 - -03
+-3 - %z
Z Antarctica/Troll 0 - -00 2005 F 12
0 Tr %s
Z Antarctica/Vostok 0 - -00 1957 D 16
-7 - +07 1994 F
+7 - %z 1994 F
0 - -00 1994 N
-7 - +07 2023 D 18 2
-5 - +05
+7 - %z 2023 D 18 2
+5 - %z
Z Asia/Almaty 5:7:48 - LMT 1924 May 2
-5 - +05 1930 Jun 21
-6 R +06/+07 1991 Mar 31 2s
-5 R +05/+06 1992 Ja 19 2s
-6 R +06/+07 2004 O 31 2s
-6 - +06 2024 Mar
-5 - +05
+5 - %z 1930 Jun 21
+6 R %z 1991 Mar 31 2s
+5 R %z 1992 Ja 19 2s
+6 R %z 2004 O 31 2s
+6 - %z 2024 Mar
+5 - %z
Z Asia/Amman 2:23:44 - LMT 1931
2 J EE%sT 2022 O 28 0s
-3 - +03
+3 - %z
Z Asia/Anadyr 11:49:56 - LMT 1924 May 2
-12 - +12 1930 Jun 21
-13 R +13/+14 1982 Ap 1 0s
-12 R +12/+13 1991 Mar 31 2s
-11 R +11/+12 1992 Ja 19 2s
-12 R +12/+13 2010 Mar 28 2s
-11 R +11/+12 2011 Mar 27 2s
-12 - +12
+12 - %z 1930 Jun 21
+13 R %z 1982 Ap 1 0s
+12 R %z 1991 Mar 31 2s
+11 R %z 1992 Ja 19 2s
+12 R %z 2010 Mar 28 2s
+11 R %z 2011 Mar 27 2s
+12 - %z
Z Asia/Aqtau 3:21:4 - LMT 1924 May 2
-4 - +04 1930 Jun 21
-5 - +05 1981 O
-6 - +06 1982 Ap
-5 R +05/+06 1991 Mar 31 2s
-4 R +04/+05 1992 Ja 19 2s
-5 R +05/+06 1994 S 25 2s
-4 R +04/+05 2004 O 31 2s
-5 - +05
+4 - %z 1930 Jun 21
+5 - %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1991 Mar 31 2s
+4 R %z 1992 Ja 19 2s
+5 R %z 1994 S 25 2s
+4 R %z 2004 O 31 2s
+5 - %z
Z Asia/Aqtobe 3:48:40 - LMT 1924 May 2
-4 - +04 1930 Jun 21
-5 - +05 1981 Ap
-5 1 +06 1981 O
-6 - +06 1982 Ap
-5 R +05/+06 1991 Mar 31 2s
-4 R +04/+05 1992 Ja 19 2s
-5 R +05/+06 2004 O 31 2s
-5 - +05
+4 - %z 1930 Jun 21
+5 - %z 1981 Ap
+5 1 %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1991 Mar 31 2s
+4 R %z 1992 Ja 19 2s
+5 R %z 2004 O 31 2s
+5 - %z
Z Asia/Ashgabat 3:53:32 - LMT 1924 May 2
-4 - +04 1930 Jun 21
-5 R +05/+06 1991 Mar 31 2
-4 R +04/+05 1992 Ja 19 2
-5 - +05
+4 - %z 1930 Jun 21
+5 R %z 1991 Mar 31 2
+4 R %z 1992 Ja 19 2
+5 - %z
Z Asia/Atyrau 3:27:44 - LMT 1924 May 2
-3 - +03 1930 Jun 21
-5 - +05 1981 O
-6 - +06 1982 Ap
-5 R +05/+06 1991 Mar 31 2s
-4 R +04/+05 1992 Ja 19 2s
-5 R +05/+06 1999 Mar 28 2s
-4 R +04/+05 2004 O 31 2s
-5 - +05
+3 - %z 1930 Jun 21
+5 - %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1991 Mar 31 2s
+4 R %z 1992 Ja 19 2s
+5 R %z 1999 Mar 28 2s
+4 R %z 2004 O 31 2s
+5 - %z
Z Asia/Baghdad 2:57:40 - LMT 1890
2:57:36 - BMT 1918
-3 - +03 1982 May
-3 IQ +03/+04
+3 - %z 1982 May
+3 IQ %z
Z Asia/Baku 3:19:24 - LMT 1924 May 2
-3 - +03 1957 Mar
-4 R +04/+05 1991 Mar 31 2s
-3 R +03/+04 1992 S lastSu 2s
-4 - +04 1996
-4 E +04/+05 1997
-4 AZ +04/+05
+3 - %z 1957 Mar
+4 R %z 1991 Mar 31 2s
+3 R %z 1992 S lastSu 2s
+4 - %z 1996
+4 E %z 1997
+4 AZ %z
Z Asia/Bangkok 6:42:4 - LMT 1880
6:42:4 - BMT 1920 Ap
-7 - +07
+7 - %z
Z Asia/Barnaul 5:35 - LMT 1919 D 10
-6 - +06 1930 Jun 21
-7 R +07/+08 1991 Mar 31 2s
-6 R +06/+07 1992 Ja 19 2s
-7 R +07/+08 1995 May 28
-6 R +06/+07 2011 Mar 27 2s
-7 - +07 2014 O 26 2s
-6 - +06 2016 Mar 27 2s
-7 - +07
+6 - %z 1930 Jun 21
+7 R %z 1991 Mar 31 2s
+6 R %z 1992 Ja 19 2s
+7 R %z 1995 May 28
+6 R %z 2011 Mar 27 2s
+7 - %z 2014 O 26 2s
+6 - %z 2016 Mar 27 2s
+7 - %z
Z Asia/Beirut 2:22 - LMT 1880
2 l EE%sT
Z Asia/Bishkek 4:58:24 - LMT 1924 May 2
-5 - +05 1930 Jun 21
-6 R +06/+07 1991 Mar 31 2s
-5 R +05/+06 1991 Au 31 2
-5 KG +05/+06 2005 Au 12
-6 - +06
+5 - %z 1930 Jun 21
+6 R %z 1991 Mar 31 2s
+5 R %z 1991 Au 31 2
+5 KG %z 2005 Au 12
+6 - %z
Z Asia/Chita 7:33:52 - LMT 1919 D 15
-8 - +08 1930 Jun 21
-9 R +09/+10 1991 Mar 31 2s
-8 R +08/+09 1992 Ja 19 2s
-9 R +09/+10 2011 Mar 27 2s
-10 - +10 2014 O 26 2s
-8 - +08 2016 Mar 27 2
-9 - +09
-Z Asia/Choibalsan 7:38 - LMT 1905 Au
-7 - +07 1978
-8 - +08 1983 Ap
-9 X +09/+10 2008 Mar 31
-8 X +08/+09
+8 - %z 1930 Jun 21
+9 R %z 1991 Mar 31 2s
+8 R %z 1992 Ja 19 2s
+9 R %z 2011 Mar 27 2s
+10 - %z 2014 O 26 2s
+8 - %z 2016 Mar 27 2
+9 - %z
Z Asia/Colombo 5:19:24 - LMT 1880
5:19:32 - MMT 1906
-5:30 - +0530 1942 Ja 5
-5:30 0:30 +06 1942 S
-5:30 1 +0630 1945 O 16 2
-5:30 - +0530 1996 May 25
-6:30 - +0630 1996 O 26 0:30
-6 - +06 2006 Ap 15 0:30
-5:30 - +0530
+5:30 - %z 1942 Ja 5
+5:30 0:30 %z 1942 S
+5:30 1 %z 1945 O 16 2
+5:30 - %z 1996 May 25
+6:30 - %z 1996 O 26 0:30
+6 - %z 2006 Ap 15 0:30
+5:30 - %z
Z Asia/Damascus 2:25:12 - LMT 1920
2 S EE%sT 2022 O 28
-3 - +03
+3 - %z
Z Asia/Dhaka 6:1:40 - LMT 1890
5:53:20 - HMT 1941 O
-6:30 - +0630 1942 May 15
-5:30 - +0530 1942 S
-6:30 - +0630 1951 S 30
-6 - +06 2009
-6 BD +06/+07
-Z Asia/Dili 8:22:20 - LMT 1912
-8 - +08 1942 F 21 23
-9 - +09 1976 May 3
-8 - +08 2000 S 17
-9 - +09
+6:30 - %z 1942 May 15
+5:30 - %z 1942 S
+6:30 - %z 1951 S 30
+6 - %z 2009
+6 BD %z
+Z Asia/Dili 8:22:20 - LMT 1911 D 31 16u
+8 - %z 1942 F 21 23
+9 - %z 1976 May 3
+8 - %z 2000 S 17
+9 - %z
Z Asia/Dubai 3:41:12 - LMT 1920
-4 - +04
+4 - %z
Z Asia/Dushanbe 4:35:12 - LMT 1924 May 2
-5 - +05 1930 Jun 21
-6 R +06/+07 1991 Mar 31 2s
-5 1 +06 1991 S 9 2s
-5 - +05
+5 - %z 1930 Jun 21
+6 R %z 1991 Mar 31 2s
+5 1 %z 1991 S 9 2s
+5 - %z
Z Asia/Famagusta 2:15:48 - LMT 1921 N 14
2 CY EE%sT 1998 S
2 E EE%sT 2016 S 8
-3 - +03 2017 O 29 1u
+3 - %z 2017 O 29 1u
2 E EE%sT
Z Asia/Gaza 2:17:52 - LMT 1900 O
2 Z EET/EEST 1948 May 15
@@ -3162,14 +3162,14 @@ Z Asia/Hebron 2:20:23 - LMT 1900 O
2 P EE%sT
Z Asia/Ho_Chi_Minh 7:6:30 - LMT 1906 Jul
7:6:30 - PLMT 1911 May
-7 - +07 1942 D 31 23
-8 - +08 1945 Mar 14 23
-9 - +09 1945 S 1 24
-7 - +07 1947 Ap
-8 - +08 1955 Jul 1 1
-7 - +07 1959 D 31 23
-8 - +08 1975 Jun 13
-7 - +07
+7 - %z 1942 D 31 23
+8 - %z 1945 Mar 14 23
+9 - %z 1945 S 1 24
+7 - %z 1947 Ap
+8 - %z 1955 Jul 1 1
+7 - %z 1959 D 31 23
+8 - %z 1975 Jun 13
+7 - %z
Z Asia/Hong_Kong 7:36:42 - LMT 1904 O 29 17u
8 - HKT 1941 Jun 15 3
8 1 HKST 1941 O 1 4
@@ -3177,96 +3177,96 @@ Z Asia/Hong_Kong 7:36:42 - LMT 1904 O 29 17u
9 - JST 1945 N 18 2
8 HK HK%sT
Z Asia/Hovd 6:6:36 - LMT 1905 Au
-6 - +06 1978
-7 X +07/+08
+6 - %z 1978
+7 X %z
Z Asia/Irkutsk 6:57:5 - LMT 1880
6:57:5 - IMT 1920 Ja 25
-7 - +07 1930 Jun 21
-8 R +08/+09 1991 Mar 31 2s
-7 R +07/+08 1992 Ja 19 2s
-8 R +08/+09 2011 Mar 27 2s
-9 - +09 2014 O 26 2s
-8 - +08
+7 - %z 1930 Jun 21
+8 R %z 1991 Mar 31 2s
+7 R %z 1992 Ja 19 2s
+8 R %z 2011 Mar 27 2s
+9 - %z 2014 O 26 2s
+8 - %z
Z Asia/Jakarta 7:7:12 - LMT 1867 Au 10
7:7:12 - BMT 1923 D 31 16:40u
-7:20 - +0720 1932 N
-7:30 - +0730 1942 Mar 23
-9 - +09 1945 S 23
-7:30 - +0730 1948 May
-8 - +08 1950 May
-7:30 - +0730 1964
+7:20 - %z 1932 N
+7:30 - %z 1942 Mar 23
+9 - %z 1945 S 23
+7:30 - %z 1948 May
+8 - %z 1950 May
+7:30 - %z 1964
7 - WIB
Z Asia/Jayapura 9:22:48 - LMT 1932 N
-9 - +09 1944 S
-9:30 - +0930 1964
+9 - %z 1944 S
+9:30 - %z 1964
9 - WIT
Z Asia/Jerusalem 2:20:54 - LMT 1880
2:20:40 - JMT 1918
2 Z I%sT
Z Asia/Kabul 4:36:48 - LMT 1890
-4 - +04 1945
-4:30 - +0430
+4 - %z 1945
+4:30 - %z
Z Asia/Kamchatka 10:34:36 - LMT 1922 N 10
-11 - +11 1930 Jun 21
-12 R +12/+13 1991 Mar 31 2s
-11 R +11/+12 1992 Ja 19 2s
-12 R +12/+13 2010 Mar 28 2s
-11 R +11/+12 2011 Mar 27 2s
-12 - +12
+11 - %z 1930 Jun 21
+12 R %z 1991 Mar 31 2s
+11 R %z 1992 Ja 19 2s
+12 R %z 2010 Mar 28 2s
+11 R %z 2011 Mar 27 2s
+12 - %z
Z Asia/Karachi 4:28:12 - LMT 1907
-5:30 - +0530 1942 S
-5:30 1 +0630 1945 O 15
-5:30 - +0530 1951 S 30
-5 - +05 1971 Mar 26
+5:30 - %z 1942 S
+5:30 1 %z 1945 O 15
+5:30 - %z 1951 S 30
+5 - %z 1971 Mar 26
5 PK PK%sT
Z Asia/Kathmandu 5:41:16 - LMT 1920
-5:30 - +0530 1986
-5:45 - +0545
+5:30 - %z 1986
+5:45 - %z
Z Asia/Khandyga 9:2:13 - LMT 1919 D 15
-8 - +08 1930 Jun 21
-9 R +09/+10 1991 Mar 31 2s
-8 R +08/+09 1992 Ja 19 2s
-9 R +09/+10 2004
-10 R +10/+11 2011 Mar 27 2s
-11 - +11 2011 S 13 0s
-10 - +10 2014 O 26 2s
-9 - +09
+8 - %z 1930 Jun 21
+9 R %z 1991 Mar 31 2s
+8 R %z 1992 Ja 19 2s
+9 R %z 2004
+10 R %z 2011 Mar 27 2s
+11 - %z 2011 S 13 0s
+10 - %z 2014 O 26 2s
+9 - %z
Z Asia/Kolkata 5:53:28 - LMT 1854 Jun 28
5:53:20 - HMT 1870
5:21:10 - MMT 1906
5:30 - IST 1941 O
-5:30 1 +0630 1942 May 15
+5:30 1 %z 1942 May 15
5:30 - IST 1942 S
-5:30 1 +0630 1945 O 15
+5:30 1 %z 1945 O 15
5:30 - IST
Z Asia/Krasnoyarsk 6:11:26 - LMT 1920 Ja 6
-6 - +06 1930 Jun 21
-7 R +07/+08 1991 Mar 31 2s
-6 R +06/+07 1992 Ja 19 2s
-7 R +07/+08 2011 Mar 27 2s
-8 - +08 2014 O 26 2s
-7 - +07
+6 - %z 1930 Jun 21
+7 R %z 1991 Mar 31 2s
+6 R %z 1992 Ja 19 2s
+7 R %z 2011 Mar 27 2s
+8 - %z 2014 O 26 2s
+7 - %z
Z Asia/Kuching 7:21:20 - LMT 1926 Mar
-7:30 - +0730 1933
-8 NB +08/+0820 1942 F 16
-9 - +09 1945 S 12
-8 - +08
+7:30 - %z 1933
+8 NB %z 1942 F 16
+9 - %z 1945 S 12
+8 - %z
Z Asia/Macau 7:34:10 - LMT 1904 O 30
8 - CST 1941 D 21 23
-9 _ +09/+10 1945 S 30 24
+9 _ %z 1945 S 30 24
8 _ C%sT
Z Asia/Magadan 10:3:12 - LMT 1924 May 2
-10 - +10 1930 Jun 21
-11 R +11/+12 1991 Mar 31 2s
-10 R +10/+11 1992 Ja 19 2s
-11 R +11/+12 2011 Mar 27 2s
-12 - +12 2014 O 26 2s
-10 - +10 2016 Ap 24 2s
-11 - +11
+10 - %z 1930 Jun 21
+11 R %z 1991 Mar 31 2s
+10 R %z 1992 Ja 19 2s
+11 R %z 2011 Mar 27 2s
+12 - %z 2014 O 26 2s
+10 - %z 2016 Ap 24 2s
+11 - %z
Z Asia/Makassar 7:57:36 - LMT 1920
7:57:36 - MMT 1932 N
-8 - +08 1942 F 9
-9 - +09 1945 S 23
+8 - %z 1942 F 9
+9 - %z 1945 S 23
8 - WITA
Z Asia/Manila -15:56 - LMT 1844 D 31
8:4 - LMT 1899 May 11
@@ -3277,45 +3277,45 @@ Z Asia/Nicosia 2:13:28 - LMT 1921 N 14
2 CY EE%sT 1998 S
2 E EE%sT
Z Asia/Novokuznetsk 5:48:48 - LMT 1924 May
-6 - +06 1930 Jun 21
-7 R +07/+08 1991 Mar 31 2s
-6 R +06/+07 1992 Ja 19 2s
-7 R +07/+08 2010 Mar 28 2s
-6 R +06/+07 2011 Mar 27 2s
-7 - +07
+6 - %z 1930 Jun 21
+7 R %z 1991 Mar 31 2s
+6 R %z 1992 Ja 19 2s
+7 R %z 2010 Mar 28 2s
+6 R %z 2011 Mar 27 2s
+7 - %z
Z Asia/Novosibirsk 5:31:40 - LMT 1919 D 14 6
-6 - +06 1930 Jun 21
-7 R +07/+08 1991 Mar 31 2s
-6 R +06/+07 1992 Ja 19 2s
-7 R +07/+08 1993 May 23
-6 R +06/+07 2011 Mar 27 2s
-7 - +07 2014 O 26 2s
-6 - +06 2016 Jul 24 2s
-7 - +07
+6 - %z 1930 Jun 21
+7 R %z 1991 Mar 31 2s
+6 R %z 1992 Ja 19 2s
+7 R %z 1993 May 23
+6 R %z 2011 Mar 27 2s
+7 - %z 2014 O 26 2s
+6 - %z 2016 Jul 24 2s
+7 - %z
Z Asia/Omsk 4:53:30 - LMT 1919 N 14
-5 - +05 1930 Jun 21
-6 R +06/+07 1991 Mar 31 2s
-5 R +05/+06 1992 Ja 19 2s
-6 R +06/+07 2011 Mar 27 2s
-7 - +07 2014 O 26 2s
-6 - +06
+5 - %z 1930 Jun 21
+6 R %z 1991 Mar 31 2s
+5 R %z 1992 Ja 19 2s
+6 R %z 2011 Mar 27 2s
+7 - %z 2014 O 26 2s
+6 - %z
Z Asia/Oral 3:25:24 - LMT 1924 May 2
-3 - +03 1930 Jun 21
-5 - +05 1981 Ap
-5 1 +06 1981 O
-6 - +06 1982 Ap
-5 R +05/+06 1989 Mar 26 2s
-4 R +04/+05 1992 Ja 19 2s
-5 R +05/+06 1992 Mar 29 2s
-4 R +04/+05 2004 O 31 2s
-5 - +05
+3 - %z 1930 Jun 21
+5 - %z 1981 Ap
+5 1 %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1989 Mar 26 2s
+4 R %z 1992 Ja 19 2s
+5 R %z 1992 Mar 29 2s
+4 R %z 2004 O 31 2s
+5 - %z
Z Asia/Pontianak 7:17:20 - LMT 1908 May
7:17:20 - PMT 1932 N
-7:30 - +0730 1942 Ja 29
-9 - +09 1945 S 23
-7:30 - +0730 1948 May
-8 - +08 1950 May
-7:30 - +0730 1964
+7:30 - %z 1942 Ja 29
+9 - %z 1945 S 23
+7:30 - %z 1948 May
+8 - %z 1950 May
+7:30 - %z 1964
8 - WITA 1988
7 - WIB
Z Asia/Pyongyang 8:23 - LMT 1908 Ap
@@ -3325,48 +3325,48 @@ Z Asia/Pyongyang 8:23 - LMT 1908 Ap
8:30 - KST 2018 May 4 23:30
9 - KST
Z Asia/Qatar 3:26:8 - LMT 1920
-4 - +04 1972 Jun
-3 - +03
+4 - %z 1972 Jun
+3 - %z
Z Asia/Qostanay 4:14:28 - LMT 1924 May 2
-4 - +04 1930 Jun 21
-5 - +05 1981 Ap
-5 1 +06 1981 O
-6 - +06 1982 Ap
-5 R +05/+06 1991 Mar 31 2s
-4 R +04/+05 1992 Ja 19 2s
-5 R +05/+06 2004 O 31 2s
-6 - +06 2024 Mar
-5 - +05
+4 - %z 1930 Jun 21
+5 - %z 1981 Ap
+5 1 %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1991 Mar 31 2s
+4 R %z 1992 Ja 19 2s
+5 R %z 2004 O 31 2s
+6 - %z 2024 Mar
+5 - %z
Z Asia/Qyzylorda 4:21:52 - LMT 1924 May 2
-4 - +04 1930 Jun 21
-5 - +05 1981 Ap
-5 1 +06 1981 O
-6 - +06 1982 Ap
-5 R +05/+06 1991 Mar 31 2s
-4 R +04/+05 1991 S 29 2s
-5 R +05/+06 1992 Ja 19 2s
-6 R +06/+07 1992 Mar 29 2s
-5 R +05/+06 2004 O 31 2s
-6 - +06 2018 D 21
-5 - +05
+4 - %z 1930 Jun 21
+5 - %z 1981 Ap
+5 1 %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1991 Mar 31 2s
+4 R %z 1991 S 29 2s
+5 R %z 1992 Ja 19 2s
+6 R %z 1992 Mar 29 2s
+5 R %z 2004 O 31 2s
+6 - %z 2018 D 21
+5 - %z
Z Asia/Riyadh 3:6:52 - LMT 1947 Mar 14
-3 - +03
+3 - %z
Z Asia/Sakhalin 9:30:48 - LMT 1905 Au 23
-9 - +09 1945 Au 25
-11 R +11/+12 1991 Mar 31 2s
-10 R +10/+11 1992 Ja 19 2s
-11 R +11/+12 1997 Mar lastSu 2s
-10 R +10/+11 2011 Mar 27 2s
-11 - +11 2014 O 26 2s
-10 - +10 2016 Mar 27 2s
-11 - +11
+9 - %z 1945 Au 25
+11 R %z 1991 Mar 31 2s
+10 R %z 1992 Ja 19 2s
+11 R %z 1997 Mar lastSu 2s
+10 R %z 2011 Mar 27 2s
+11 - %z 2014 O 26 2s
+10 - %z 2016 Mar 27 2s
+11 - %z
Z Asia/Samarkand 4:27:53 - LMT 1924 May 2
-4 - +04 1930 Jun 21
-5 - +05 1981 Ap
-5 1 +06 1981 O
-6 - +06 1982 Ap
-5 R +05/+06 1992
-5 - +05
+4 - %z 1930 Jun 21
+5 - %z 1981 Ap
+5 1 %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1992
+5 - %z
Z Asia/Seoul 8:27:52 - LMT 1908 Ap
8:30 - KST 1912
9 - JST 1945 S 8
@@ -3378,161 +3378,147 @@ Z Asia/Shanghai 8:5:43 - LMT 1901
8 CN C%sT
Z Asia/Singapore 6:55:25 - LMT 1901
6:55:25 - SMT 1905 Jun
-7 - +07 1933
-7 0:20 +0720 1936
-7:20 - +0720 1941 S
-7:30 - +0730 1942 F 16
-9 - +09 1945 S 12
-7:30 - +0730 1981 D 31 16u
-8 - +08
+7 - %z 1933
+7 0:20 %z 1936
+7:20 - %z 1941 S
+7:30 - %z 1942 F 16
+9 - %z 1945 S 12
+7:30 - %z 1981 D 31 16u
+8 - %z
Z Asia/Srednekolymsk 10:14:52 - LMT 1924 May 2
-10 - +10 1930 Jun 21
-11 R +11/+12 1991 Mar 31 2s
-10 R +10/+11 1992 Ja 19 2s
-11 R +11/+12 2011 Mar 27 2s
-12 - +12 2014 O 26 2s
-11 - +11
+10 - %z 1930 Jun 21
+11 R %z 1991 Mar 31 2s
+10 R %z 1992 Ja 19 2s
+11 R %z 2011 Mar 27 2s
+12 - %z 2014 O 26 2s
+11 - %z
Z Asia/Taipei 8:6 - LMT 1896
8 - CST 1937 O
9 - JST 1945 S 21 1
8 f C%sT
Z Asia/Tashkent 4:37:11 - LMT 1924 May 2
-5 - +05 1930 Jun 21
-6 R +06/+07 1991 Mar 31 2
-5 R +05/+06 1992
-5 - +05
+5 - %z 1930 Jun 21
+6 R %z 1991 Mar 31 2
+5 R %z 1992
+5 - %z
Z Asia/Tbilisi 2:59:11 - LMT 1880
2:59:11 - TBMT 1924 May 2
-3 - +03 1957 Mar
-4 R +04/+05 1991 Mar 31 2s
-3 R +03/+04 1992
-3 e +03/+04 1994 S lastSu
-4 e +04/+05 1996 O lastSu
-4 1 +05 1997 Mar lastSu
-4 e +04/+05 2004 Jun 27
-3 R +03/+04 2005 Mar lastSu 2
-4 - +04
+3 - %z 1957 Mar
+4 R %z 1991 Mar 31 2s
+3 R %z 1992
+3 e %z 1994 S lastSu
+4 e %z 1996 O lastSu
+4 1 %z 1997 Mar lastSu
+4 e %z 2004 Jun 27
+3 R %z 2005 Mar lastSu 2
+4 - %z
Z Asia/Tehran 3:25:44 - LMT 1916
3:25:44 - TMT 1935 Jun 13
-3:30 i +0330/+0430 1977 O 20 24
-4 i +04/+05 1979
-3:30 i +0330/+0430
+3:30 i %z 1977 O 20 24
+4 i %z 1979
+3:30 i %z
Z Asia/Thimphu 5:58:36 - LMT 1947 Au 15
-5:30 - +0530 1987 O
-6 - +06
+5:30 - %z 1987 O
+6 - %z
Z Asia/Tokyo 9:18:59 - LMT 1887 D 31 15u
9 JP J%sT
Z Asia/Tomsk 5:39:51 - LMT 1919 D 22
-6 - +06 1930 Jun 21
-7 R +07/+08 1991 Mar 31 2s
-6 R +06/+07 1992 Ja 19 2s
-7 R +07/+08 2002 May 1 3
-6 R +06/+07 2011 Mar 27 2s
-7 - +07 2014 O 26 2s
-6 - +06 2016 May 29 2s
-7 - +07
+6 - %z 1930 Jun 21
+7 R %z 1991 Mar 31 2s
+6 R %z 1992 Ja 19 2s
+7 R %z 2002 May 1 3
+6 R %z 2011 Mar 27 2s
+7 - %z 2014 O 26 2s
+6 - %z 2016 May 29 2s
+7 - %z
Z Asia/Ulaanbaatar 7:7:32 - LMT 1905 Au
-7 - +07 1978
-8 X +08/+09
+7 - %z 1978
+8 X %z
Z Asia/Urumqi 5:50:20 - LMT 1928
-6 - +06
+6 - %z
Z Asia/Ust-Nera 9:32:54 - LMT 1919 D 15
-8 - +08 1930 Jun 21
-9 R +09/+10 1981 Ap
-11 R +11/+12 1991 Mar 31 2s
-10 R +10/+11 1992 Ja 19 2s
-11 R +11/+12 2011 Mar 27 2s
-12 - +12 2011 S 13 0s
-11 - +11 2014 O 26 2s
-10 - +10
+8 - %z 1930 Jun 21
+9 R %z 1981 Ap
+11 R %z 1991 Mar 31 2s
+10 R %z 1992 Ja 19 2s
+11 R %z 2011 Mar 27 2s
+12 - %z 2011 S 13 0s
+11 - %z 2014 O 26 2s
+10 - %z
Z Asia/Vladivostok 8:47:31 - LMT 1922 N 15
-9 - +09 1930 Jun 21
-10 R +10/+11 1991 Mar 31 2s
-9 R +09/+10 1992 Ja 19 2s
-10 R +10/+11 2011 Mar 27 2s
-11 - +11 2014 O 26 2s
-10 - +10
+9 - %z 1930 Jun 21
+10 R %z 1991 Mar 31 2s
+9 R %z 1992 Ja 19 2s
+10 R %z 2011 Mar 27 2s
+11 - %z 2014 O 26 2s
+10 - %z
Z Asia/Yakutsk 8:38:58 - LMT 1919 D 15
-8 - +08 1930 Jun 21
-9 R +09/+10 1991 Mar 31 2s
-8 R +08/+09 1992 Ja 19 2s
-9 R +09/+10 2011 Mar 27 2s
-10 - +10 2014 O 26 2s
-9 - +09
+8 - %z 1930 Jun 21
+9 R %z 1991 Mar 31 2s
+8 R %z 1992 Ja 19 2s
+9 R %z 2011 Mar 27 2s
+10 - %z 2014 O 26 2s
+9 - %z
Z Asia/Yangon 6:24:47 - LMT 1880
6:24:47 - RMT 1920
-6:30 - +0630 1942 May
-9 - +09 1945 May 3
-6:30 - +0630
+6:30 - %z 1942 May
+9 - %z 1945 May 3
+6:30 - %z
Z Asia/Yekaterinburg 4:2:33 - LMT 1916 Jul 3
3:45:5 - PMT 1919 Jul 15 4
-4 - +04 1930 Jun 21
-5 R +05/+06 1991 Mar 31 2s
-4 R +04/+05 1992 Ja 19 2s
-5 R +05/+06 2011 Mar 27 2s
-6 - +06 2014 O 26 2s
-5 - +05
+4 - %z 1930 Jun 21
+5 R %z 1991 Mar 31 2s
+4 R %z 1992 Ja 19 2s
+5 R %z 2011 Mar 27 2s
+6 - %z 2014 O 26 2s
+5 - %z
Z Asia/Yerevan 2:58 - LMT 1924 May 2
-3 - +03 1957 Mar
-4 R +04/+05 1991 Mar 31 2s
-3 R +03/+04 1995 S 24 2s
-4 - +04 1997
-4 R +04/+05 2011
-4 AM +04/+05
+3 - %z 1957 Mar
+4 R %z 1991 Mar 31 2s
+3 R %z 1995 S 24 2s
+4 - %z 1997
+4 R %z 2011
+4 AM %z
Z Atlantic/Azores -1:42:40 - LMT 1884
-1:54:32 - HMT 1912 Ja 1 2u
--2 p -02/-01 1942 Ap 25 22s
--2 p +00 1942 Au 15 22s
--2 p -02/-01 1943 Ap 17 22s
--2 p +00 1943 Au 28 22s
--2 p -02/-01 1944 Ap 22 22s
--2 p +00 1944 Au 26 22s
--2 p -02/-01 1945 Ap 21 22s
--2 p +00 1945 Au 25 22s
--2 p -02/-01 1966 Ap 3 2
--1 p -01/+00 1983 S 25 1s
--1 W- -01/+00 1992 S 27 1s
-0 E WE%sT 1993 Mar 28 1u
--1 E -01/+00
+-2 p %z 1966 O 2 2s
+-1 - %z 1982 Mar 28 0s
+-1 p %z 1986
+-1 E %z 1992 D 27 1s
+0 E WE%sT 1993 Jun 17 1u
+-1 E %z
Z Atlantic/Bermuda -4:19:18 - LMT 1890
-4:19:18 Be BMT/BST 1930 Ja 1 2
-4 Be A%sT 1974 Ap 28 2
-4 C A%sT 1976
-4 u A%sT
Z Atlantic/Canary -1:1:36 - LMT 1922 Mar
--1 - -01 1946 S 30 1
+-1 - %z 1946 S 30 1
0 - WET 1980 Ap 6 0s
0 1 WEST 1980 S 28 1u
0 E WE%sT
Z Atlantic/Cape_Verde -1:34:4 - LMT 1912 Ja 1 2u
--2 - -02 1942 S
--2 1 -01 1945 O 15
--2 - -02 1975 N 25 2
--1 - -01
+-2 - %z 1942 S
+-2 1 %z 1945 O 15
+-2 - %z 1975 N 25 2
+-1 - %z
Z Atlantic/Faroe -0:27:4 - LMT 1908 Ja 11
0 - WET 1981
0 E WE%sT
Z Atlantic/Madeira -1:7:36 - LMT 1884
-1:7:36 - FMT 1912 Ja 1 1u
--1 p -01/+00 1942 Ap 25 22s
--1 p +01 1942 Au 15 22s
--1 p -01/+00 1943 Ap 17 22s
--1 p +01 1943 Au 28 22s
--1 p -01/+00 1944 Ap 22 22s
--1 p +01 1944 Au 26 22s
--1 p -01/+00 1945 Ap 21 22s
--1 p +01 1945 Au 25 22s
--1 p -01/+00 1966 Ap 3 2
-0 p WE%sT 1983 S 25 1s
+-1 p %z 1966 O 2 2s
+0 - WET 1982 Ap 4
+0 p WE%sT 1986 Jul 31
0 E WE%sT
Z Atlantic/South_Georgia -2:26:8 - LMT 1890
--2 - -02
+-2 - %z
Z Atlantic/Stanley -3:51:24 - LMT 1890
-3:51:24 - SMT 1912 Mar 12
--4 FK -04/-03 1983 May
--3 FK -03/-02 1985 S 15
--4 FK -04/-03 2010 S 5 2
--3 - -03
+-4 FK %z 1983 May
+-3 FK %z 1985 S 15
+-4 FK %z 2010 S 5 2
+-3 - %z
Z Australia/Adelaide 9:14:20 - LMT 1895 F
9 - ACST 1899 May
9:30 AU AC%sT 1971
@@ -3550,8 +3536,8 @@ Z Australia/Darwin 8:43:20 - LMT 1895 F
9 - ACST 1899 May
9:30 AU AC%sT
Z Australia/Eucla 8:35:28 - LMT 1895 D
-8:45 AU +0845/+0945 1943 Jul
-8:45 AW +0845/+0945
+8:45 AU %z 1943 Jul
+8:45 AW %z
Z Australia/Hobart 9:49:16 - LMT 1895 S
10 AT AE%sT 1919 O 24
10 AU AE%sT 1967
@@ -3562,8 +3548,8 @@ Z Australia/Lindeman 9:55:56 - LMT 1895
10 Ho AE%sT
Z Australia/Lord_Howe 10:36:20 - LMT 1895 F
10 - AEST 1981 Mar
-10:30 LH +1030/+1130 1985 Jul
-10:30 LH +1030/+11
+10:30 LH %z 1985 Jul
+10:30 LH %z
Z Australia/Melbourne 9:39:52 - LMT 1895 F
10 AU AE%sT 1971
10 AV AE%sT
@@ -3573,52 +3559,47 @@ Z Australia/Perth 7:43:24 - LMT 1895 D
Z Australia/Sydney 10:4:52 - LMT 1895 F
10 AU AE%sT 1971
10 AN AE%sT
-Z CET 1 c CE%sT
-Z CST6CDT -6 u C%sT
-Z EET 2 E EE%sT
-Z EST -5 - EST
-Z EST5EDT -5 u E%sT
Z Etc/GMT 0 - GMT
-Z Etc/GMT+1 -1 - -01
-Z Etc/GMT+10 -10 - -10
-Z Etc/GMT+11 -11 - -11
-Z Etc/GMT+12 -12 - -12
-Z Etc/GMT+2 -2 - -02
-Z Etc/GMT+3 -3 - -03
-Z Etc/GMT+4 -4 - -04
-Z Etc/GMT+5 -5 - -05
-Z Etc/GMT+6 -6 - -06
-Z Etc/GMT+7 -7 - -07
-Z Etc/GMT+8 -8 - -08
-Z Etc/GMT+9 -9 - -09
-Z Etc/GMT-1 1 - +01
-Z Etc/GMT-10 10 - +10
-Z Etc/GMT-11 11 - +11
-Z Etc/GMT-12 12 - +12
-Z Etc/GMT-13 13 - +13
-Z Etc/GMT-14 14 - +14
-Z Etc/GMT-2 2 - +02
-Z Etc/GMT-3 3 - +03
-Z Etc/GMT-4 4 - +04
-Z Etc/GMT-5 5 - +05
-Z Etc/GMT-6 6 - +06
-Z Etc/GMT-7 7 - +07
-Z Etc/GMT-8 8 - +08
-Z Etc/GMT-9 9 - +09
+Z Etc/GMT+1 -1 - %z
+Z Etc/GMT+10 -10 - %z
+Z Etc/GMT+11 -11 - %z
+Z Etc/GMT+12 -12 - %z
+Z Etc/GMT+2 -2 - %z
+Z Etc/GMT+3 -3 - %z
+Z Etc/GMT+4 -4 - %z
+Z Etc/GMT+5 -5 - %z
+Z Etc/GMT+6 -6 - %z
+Z Etc/GMT+7 -7 - %z
+Z Etc/GMT+8 -8 - %z
+Z Etc/GMT+9 -9 - %z
+Z Etc/GMT-1 1 - %z
+Z Etc/GMT-10 10 - %z
+Z Etc/GMT-11 11 - %z
+Z Etc/GMT-12 12 - %z
+Z Etc/GMT-13 13 - %z
+Z Etc/GMT-14 14 - %z
+Z Etc/GMT-2 2 - %z
+Z Etc/GMT-3 3 - %z
+Z Etc/GMT-4 4 - %z
+Z Etc/GMT-5 5 - %z
+Z Etc/GMT-6 6 - %z
+Z Etc/GMT-7 7 - %z
+Z Etc/GMT-8 8 - %z
+Z Etc/GMT-9 9 - %z
Z Etc/UTC 0 - UTC
Z Europe/Andorra 0:6:4 - LMT 1901
0 - WET 1946 S 30
1 - CET 1985 Mar 31 2
1 E CE%sT
Z Europe/Astrakhan 3:12:12 - LMT 1924 May
-3 - +03 1930 Jun 21
-4 R +04/+05 1989 Mar 26 2s
-3 R +03/+04 1991 Mar 31 2s
-4 - +04 1992 Mar 29 2s
-3 R +03/+04 2011 Mar 27 2s
-4 - +04 2014 O 26 2s
-3 - +03 2016 Mar 27 2s
-4 - +04
+3 - %z 1930 Jun 21
+4 R %z 1989 Mar 26 2s
+3 R %z 1991 Mar 31 2s
+4 - %z 1992 Mar 29 2s
+3 R %z 2011 Mar 27 2s
+4 - %z 2014 O 26 2s
+3 - %z 2016 Mar 27 2s
+4 - %z
Z Europe/Athens 1:34:52 - LMT 1895 S 14
1:34:52 - AMT 1916 Jul 28 0:1
2 g EE%sT 1941 Ap 30
@@ -3691,7 +3672,7 @@ Z Europe/Helsinki 1:39:49 - LMT 1878 May 31
Z Europe/Istanbul 1:55:52 - LMT 1880
1:56:56 - IMT 1910 O
2 T EE%sT 1978 Jun 29
-3 T +03/+04 1984 N 1 2
+3 T %z 1984 N 1 2
2 T EE%sT 2007
2 E EE%sT 2011 Mar 27 1u
2 - EET 2011 Mar 28 1u
@@ -3700,19 +3681,19 @@ Z Europe/Istanbul 1:55:52 - LMT 1880
2 E EE%sT 2015 O 25 1u
2 1 EEST 2015 N 8 1u
2 E EE%sT 2016 S 7
-3 - +03
+3 - %z
Z Europe/Kaliningrad 1:22 - LMT 1893 Ap
1 c CE%sT 1945 Ap 10
2 O EE%sT 1946 Ap 7
3 R MSK/MSD 1989 Mar 26 2s
2 R EE%sT 2011 Mar 27 2s
-3 - +03 2014 O 26 2s
+3 - %z 2014 O 26 2s
2 - EET
Z Europe/Kirov 3:18:48 - LMT 1919 Jul 1 0u
-3 - +03 1930 Jun 21
-4 R +04/+05 1989 Mar 26 2s
+3 - %z 1930 Jun 21
+4 R %z 1989 Mar 26 2s
3 R MSK/MSD 1991 Mar 31 2s
-4 - +04 1992 Mar 29 2s
+4 - %z 1992 Mar 29 2s
3 R MSK/MSD 2011 Mar 27 2s
4 - MSK 2014 O 26 2s
3 - MSK
@@ -3727,10 +3708,10 @@ Z Europe/Kyiv 2:2:4 - LMT 1880
2 E EE%sT
Z Europe/Lisbon -0:36:45 - LMT 1884
-0:36:45 - LMT 1912 Ja 1 0u
-0 p WE%sT 1966 Ap 3 2
+0 p WE%sT 1966 O 2 2s
1 - CET 1976 S 26 1
-0 p WE%sT 1983 S 25 1s
-0 W- WE%sT 1992 S 27 1s
+0 p WE%sT 1986
+0 E WE%sT 1992 S 27 1u
1 E CE%sT 1996 Mar 31 1u
0 E WE%sT
Z Europe/London -0:1:15 - LMT 1847 D
@@ -3754,7 +3735,7 @@ Z Europe/Minsk 1:50:16 - LMT 1880
3 R MSK/MSD 1990
3 - MSK 1991 Mar 31 2s
2 R EE%sT 2011 Mar 27 2s
-3 - +03
+3 - %z
Z Europe/Moscow 2:30:17 - LMT 1880
2:30:17 - MMT 1916 Jul 3
2:31:19 R %s 1919 Jul 1 0u
@@ -3802,24 +3783,24 @@ Z Europe/Rome 0:49:56 - LMT 1866 D 12
1 I CE%sT 1980
1 E CE%sT
Z Europe/Samara 3:20:20 - LMT 1919 Jul 1 0u
-3 - +03 1930 Jun 21
-4 - +04 1935 Ja 27
-4 R +04/+05 1989 Mar 26 2s
-3 R +03/+04 1991 Mar 31 2s
-2 R +02/+03 1991 S 29 2s
-3 - +03 1991 O 20 3
-4 R +04/+05 2010 Mar 28 2s
-3 R +03/+04 2011 Mar 27 2s
-4 - +04
+3 - %z 1930 Jun 21
+4 - %z 1935 Ja 27
+4 R %z 1989 Mar 26 2s
+3 R %z 1991 Mar 31 2s
+2 R %z 1991 S 29 2s
+3 - %z 1991 O 20 3
+4 R %z 2010 Mar 28 2s
+3 R %z 2011 Mar 27 2s
+4 - %z
Z Europe/Saratov 3:4:18 - LMT 1919 Jul 1 0u
-3 - +03 1930 Jun 21
-4 R +04/+05 1988 Mar 27 2s
-3 R +03/+04 1991 Mar 31 2s
-4 - +04 1992 Mar 29 2s
-3 R +03/+04 2011 Mar 27 2s
-4 - +04 2014 O 26 2s
-3 - +03 2016 D 4 2s
-4 - +04
+3 - %z 1930 Jun 21
+4 R %z 1988 Mar 27 2s
+3 R %z 1991 Mar 31 2s
+4 - %z 1992 Mar 29 2s
+3 R %z 2011 Mar 27 2s
+4 - %z 2014 O 26 2s
+3 - %z 2016 D 4 2s
+4 - %z
Z Europe/Simferopol 2:16:24 - LMT 1880
2:16 - SMT 1924 May 2
2 - EET 1930 Jun 21
@@ -3863,14 +3844,14 @@ Z Europe/Tirane 1:19:20 - LMT 1914
1 q CE%sT 1984 Jul
1 E CE%sT
Z Europe/Ulyanovsk 3:13:36 - LMT 1919 Jul 1 0u
-3 - +03 1930 Jun 21
-4 R +04/+05 1989 Mar 26 2s
-3 R +03/+04 1991 Mar 31 2s
-2 R +02/+03 1992 Ja 19 2s
-3 R +03/+04 2011 Mar 27 2s
-4 - +04 2014 O 26 2s
-3 - +03 2016 Mar 27 2s
-4 - +04
+3 - %z 1930 Jun 21
+4 R %z 1989 Mar 26 2s
+3 R %z 1991 Mar 31 2s
+2 R %z 1992 Ja 19 2s
+3 R %z 2011 Mar 27 2s
+4 - %z 2014 O 26 2s
+3 - %z 2016 Mar 27 2s
+4 - %z
Z Europe/Vienna 1:5:21 - LMT 1893 Ap
1 c CE%sT 1920
1 a CE%sT 1940 Ap 1 2s
@@ -3895,15 +3876,15 @@ Z Europe/Vilnius 1:41:16 - LMT 1880
2 - EET 2003
2 E EE%sT
Z Europe/Volgograd 2:57:40 - LMT 1920 Ja 3
-3 - +03 1930 Jun 21
-4 - +04 1961 N 11
-4 R +04/+05 1988 Mar 27 2s
+3 - %z 1930 Jun 21
+4 - %z 1961 N 11
+4 R %z 1988 Mar 27 2s
3 R MSK/MSD 1991 Mar 31 2s
-4 - +04 1992 Mar 29 2s
+4 - %z 1992 Mar 29 2s
3 R MSK/MSD 2011 Mar 27 2s
4 - MSK 2014 O 26 2s
3 - MSK 2018 O 28 2s
-4 - +04 2020 D 27 2s
+4 - %z 2020 D 27 2s
3 - MSK
Z Europe/Warsaw 1:24 - LMT 1880
1:24 - WMT 1915 Au 5
@@ -3919,58 +3900,53 @@ Z Europe/Zurich 0:34:8 - LMT 1853 Jul 16
1 CH CE%sT 1981
1 E CE%sT
Z Factory 0 - -00
-Z HST -10 - HST
Z Indian/Chagos 4:49:40 - LMT 1907
-5 - +05 1996
-6 - +06
+5 - %z 1996
+6 - %z
Z Indian/Maldives 4:54 - LMT 1880
4:54 - MMT 1960
-5 - +05
+5 - %z
Z Indian/Mauritius 3:50 - LMT 1907
-4 MU +04/+05
-Z MET 1 c ME%sT
-Z MST -7 - MST
-Z MST7MDT -7 u M%sT
-Z PST8PDT -8 u P%sT
+4 MU %z
Z Pacific/Apia 12:33:4 - LMT 1892 Jul 5
-11:26:56 - LMT 1911
--11:30 - -1130 1950
--11 WS -11/-10 2011 D 29 24
-13 WS +13/+14
+-11:30 - %z 1950
+-11 WS %z 2011 D 29 24
+13 WS %z
Z Pacific/Auckland 11:39:4 - LMT 1868 N 2
11:30 NZ NZ%sT 1946
12 NZ NZ%sT
Z Pacific/Bougainville 10:22:16 - LMT 1880
9:48:32 - PMMT 1895
-10 - +10 1942 Jul
-9 - +09 1945 Au 21
-10 - +10 2014 D 28 2
-11 - +11
+10 - %z 1942 Jul
+9 - %z 1945 Au 21
+10 - %z 2014 D 28 2
+11 - %z
Z Pacific/Chatham 12:13:48 - LMT 1868 N 2
-12:15 - +1215 1946
-12:45 k +1245/+1345
+12:15 - %z 1946
+12:45 k %z
Z Pacific/Easter -7:17:28 - LMT 1890
-7:17:28 - EMT 1932 S
--7 x -07/-06 1982 Mar 14 3u
--6 x -06/-05
+-7 x %z 1982 Mar 14 3u
+-6 x %z
Z Pacific/Efate 11:13:16 - LMT 1912 Ja 13
-11 VU +11/+12
+11 VU %z
Z Pacific/Fakaofo -11:24:56 - LMT 1901
--11 - -11 2011 D 30
-13 - +13
+-11 - %z 2011 D 30
+13 - %z
Z Pacific/Fiji 11:55:44 - LMT 1915 O 26
-12 FJ +12/+13
+12 FJ %z
Z Pacific/Galapagos -5:58:24 - LMT 1931
--5 - -05 1986
--6 EC -06/-05
+-5 - %z 1986
+-6 EC %z
Z Pacific/Gambier -8:59:48 - LMT 1912 O
--9 - -09
+-9 - %z
Z Pacific/Guadalcanal 10:39:48 - LMT 1912 O
-11 - +11
+11 - %z
Z Pacific/Guam -14:21 - LMT 1844 D 31
9:39 - LMT 1901
10 - GST 1941 D 10
-9 - +09 1944 Jul 31
+9 - %z 1944 Jul 31
10 Gu G%sT 2000 D 23
10 - ChST
Z Pacific/Honolulu -10:31:26 - LMT 1896 Ja 13 12
@@ -3979,74 +3955,73 @@ Z Pacific/Honolulu -10:31:26 - LMT 1896 Ja 13 12
-10:30 u H%sT 1947 Jun 8 2
-10 - HST
Z Pacific/Kanton 0 - -00 1937 Au 31
--12 - -12 1979 O
--11 - -11 1994 D 31
-13 - +13
+-12 - %z 1979 O
+-11 - %z 1994 D 31
+13 - %z
Z Pacific/Kiritimati -10:29:20 - LMT 1901
--10:40 - -1040 1979 O
--10 - -10 1994 D 31
-14 - +14
+-10:40 - %z 1979 O
+-10 - %z 1994 D 31
+14 - %z
Z Pacific/Kosrae -13:8:4 - LMT 1844 D 31
10:51:56 - LMT 1901
-11 - +11 1914 O
-9 - +09 1919 F
-11 - +11 1937
-10 - +10 1941 Ap
-9 - +09 1945 Au
-11 - +11 1969 O
-12 - +12 1999
-11 - +11
+11 - %z 1914 O
+9 - %z 1919 F
+11 - %z 1937
+10 - %z 1941 Ap
+9 - %z 1945 Au
+11 - %z 1969 O
+12 - %z 1999
+11 - %z
Z Pacific/Kwajalein 11:9:20 - LMT 1901
-11 - +11 1937
-10 - +10 1941 Ap
-9 - +09 1944 F 6
-11 - +11 1969 O
--12 - -12 1993 Au 20 24
-12 - +12
+11 - %z 1937
+10 - %z 1941 Ap
+9 - %z 1944 F 6
+11 - %z 1969 O
+-12 - %z 1993 Au 20 24
+12 - %z
Z Pacific/Marquesas -9:18 - LMT 1912 O
--9:30 - -0930
+-9:30 - %z
Z Pacific/Nauru 11:7:40 - LMT 1921 Ja 15
-11:30 - +1130 1942 Au 29
-9 - +09 1945 S 8
-11:30 - +1130 1979 F 10 2
-12 - +12
+11:30 - %z 1942 Au 29
+9 - %z 1945 S 8
+11:30 - %z 1979 F 10 2
+12 - %z
Z Pacific/Niue -11:19:40 - LMT 1952 O 16
--11:20 - -1120 1964 Jul
--11 - -11
+-11:20 - %z 1964 Jul
+-11 - %z
Z Pacific/Norfolk 11:11:52 - LMT 1901
-11:12 - +1112 1951
-11:30 - +1130 1974 O 27 2s
-11:30 1 +1230 1975 Mar 2 2s
-11:30 - +1130 2015 O 4 2s
-11 - +11 2019 Jul
-11 AN +11/+12
+11:12 - %z 1951
+11:30 - %z 1974 O 27 2s
+11:30 1 %z 1975 Mar 2 2s
+11:30 - %z 2015 O 4 2s
+11 - %z 2019 Jul
+11 AN %z
Z Pacific/Noumea 11:5:48 - LMT 1912 Ja 13
-11 NC +11/+12
+11 NC %z
Z Pacific/Pago_Pago 12:37:12 - LMT 1892 Jul 5
-11:22:48 - LMT 1911
-11 - SST
Z Pacific/Palau -15:2:4 - LMT 1844 D 31
8:57:56 - LMT 1901
-9 - +09
+9 - %z
Z Pacific/Pitcairn -8:40:20 - LMT 1901
--8:30 - -0830 1998 Ap 27
--8 - -08
+-8:30 - %z 1998 Ap 27
+-8 - %z
Z Pacific/Port_Moresby 9:48:40 - LMT 1880
9:48:32 - PMMT 1895
-10 - +10
+10 - %z
Z Pacific/Rarotonga 13:20:56 - LMT 1899 D 26
-10:39:4 - LMT 1952 O 16
--10:30 - -1030 1978 N 12
--10 CK -10/-0930
+-10:30 - %z 1978 N 12
+-10 CK %z
Z Pacific/Tahiti -9:58:16 - LMT 1912 O
--10 - -10
+-10 - %z
Z Pacific/Tarawa 11:32:4 - LMT 1901
-12 - +12
+12 - %z
Z Pacific/Tongatapu 12:19:12 - LMT 1945 S 10
-12:20 - +1220 1961
-13 - +13 1999
-13 TO +13/+14
-Z WET 0 E WE%sT
+12:20 - %z 1961
+13 - %z 1999
+13 TO %z
L Etc/GMT GMT
L Australia/Sydney Australia/ACT
L Australia/Lord_Howe Australia/LHI
@@ -4062,6 +4037,8 @@ L America/Rio_Branco Brazil/Acre
L America/Noronha Brazil/DeNoronha
L America/Sao_Paulo Brazil/East
L America/Manaus Brazil/West
+L Europe/Brussels CET
+L America/Chicago CST6CDT
L America/Halifax Canada/Atlantic
L America/Winnipeg Canada/Central
L America/Toronto Canada/Eastern
@@ -4073,6 +4050,9 @@ L America/Whitehorse Canada/Yukon
L America/Santiago Chile/Continental
L Pacific/Easter Chile/EasterIsland
L America/Havana Cuba
+L Europe/Athens EET
+L America/Panama EST
+L America/New_York EST5EDT
L Africa/Cairo Egypt
L Europe/Dublin Eire
L Etc/GMT Etc/GMT+0
@@ -4096,6 +4076,9 @@ L America/Jamaica Jamaica
L Asia/Tokyo Japan
L Pacific/Kwajalein Kwajalein
L Africa/Tripoli Libya
+L Europe/Brussels MET
+L America/Phoenix MST
+L America/Denver MST7MDT
L America/Tijuana Mexico/BajaNorte
L America/Mazatlan Mexico/BajaSur
L America/Mexico_City Mexico/General
@@ -4259,6 +4242,7 @@ L America/Denver America/Shiprock
L America/Toronto America/Thunder_Bay
L America/Edmonton America/Yellowknife
L Pacific/Auckland Antarctica/South_Pole
+L Asia/Ulaanbaatar Asia/Choibalsan
L Asia/Shanghai Asia/Chongqing
L Asia/Shanghai Asia/Harbin
L Asia/Urumqi Asia/Kashgar
@@ -4273,6 +4257,7 @@ L Europe/Kyiv Europe/Zaporozhye
L Pacific/Kanton Pacific/Enderbury
L Pacific/Honolulu Pacific/Johnston
L Pacific/Port_Moresby Pacific/Yap
+L Europe/Lisbon WET
L Africa/Nairobi Africa/Asmera
L America/Nuuk America/Godthab
L Asia/Ashgabat Asia/Ashkhabad
@@ -4290,5 +4275,7 @@ L Asia/Ulaanbaatar Asia/Ulan_Bator
L Atlantic/Faroe Atlantic/Faeroe
L Europe/Kyiv Europe/Kiev
L Asia/Nicosia Europe/Nicosia
+L Pacific/Honolulu HST
+L America/Los_Angeles PST8PDT
L Pacific/Guadalcanal Pacific/Ponape
L Pacific/Port_Moresby Pacific/Truk
diff --git a/lib/tzdata/zoneinfo/zone.tab b/lib/tzdata/zoneinfo/zone.tab
index 3fa9306a..bfc0b593 100644
--- a/lib/tzdata/zoneinfo/zone.tab
+++ b/lib/tzdata/zoneinfo/zone.tab
@@ -264,8 +264,7 @@ MK +4159+02126 Europe/Skopje
ML +1239-00800 Africa/Bamako
MM +1647+09610 Asia/Yangon
MN +4755+10653 Asia/Ulaanbaatar most of Mongolia
-MN +4801+09139 Asia/Hovd Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan
-MN +4804+11430 Asia/Choibalsan Dornod, Sukhbaatar
+MN +4801+09139 Asia/Hovd Bayan-Olgii, Hovd, Uvs
MO +221150+1133230 Asia/Macau
MP +1512+14545 Pacific/Saipan
MQ +1436-06105 America/Martinique
diff --git a/lib/tzdata/zoneinfo/zone1970.tab b/lib/tzdata/zoneinfo/zone1970.tab
index abd94897..7726f39a 100644
--- a/lib/tzdata/zoneinfo/zone1970.tab
+++ b/lib/tzdata/zoneinfo/zone1970.tab
@@ -209,8 +209,7 @@ MD +4700+02850 Europe/Chisinau
MH +0905+16720 Pacific/Kwajalein Kwajalein
MM,CC +1647+09610 Asia/Yangon
MN +4755+10653 Asia/Ulaanbaatar most of Mongolia
-MN +4801+09139 Asia/Hovd Bayan-Ölgii, Govi-Altai, Hovd, Uvs, Zavkhan
-MN +4804+11430 Asia/Choibalsan Dornod, Sükhbaatar
+MN +4801+09139 Asia/Hovd Bayan-Ölgii, Hovd, Uvs
MO +221150+1133230 Asia/Macau
MQ +1436-06105 America/Martinique
MT +3554+01431 Europe/Malta
diff --git a/lib/tzdata/zoneinfo/zonenow.tab b/lib/tzdata/zoneinfo/zonenow.tab
index b6f29109..01f536b3 100644
--- a/lib/tzdata/zoneinfo/zonenow.tab
+++ b/lib/tzdata/zoneinfo/zonenow.tab
@@ -5,7 +5,7 @@
# From Paul Eggert (2023-12-18):
# This file contains a table where each row stands for a timezone
# where civil timestamps are predicted to agree from now on.
-# This file is like zone1970.tab (see zone1970.tab's coments),
+# This file is like zone1970.tab (see zone1970.tab's comments),
# but with the following changes:
#
# 1. Each timezone corresponds to a set of clocks that are planned
@@ -123,8 +123,6 @@ XX +1455-02331 Atlantic/Cape_Verde Cape Verde
#
# -01/+00 (EU DST)
XX +3744-02540 Atlantic/Azores Azores
-# -01/+00 (EU DST) until 2024-03-31; then -02/-01 (EU DST)
-XX +7029-02158 America/Scoresbysund Ittoqqortoormiit
#
# +00 - GMT
XX +0519-00402 Africa/Abidjan far western Africa; Iceland ("GMT")
@@ -199,7 +197,7 @@ XX +2518+05518 Asia/Dubai Russia; Caucasus; Persian Gulf; Seychelles; Réunion
XX +3431+06912 Asia/Kabul Afghanistan
#
# +05
-XX +4120+06918 Asia/Tashkent Russia; west Kazakhstan; Tajikistan; Turkmenistan; Uzbekistan; Maldives
+XX +4120+06918 Asia/Tashkent Russia; Kazakhstan; Tajikistan; Turkmenistan; Uzbekistan; Maldives
#
# +05 - PKT
XX +2452+06703 Asia/Karachi Pakistan ("PKT")
@@ -215,8 +213,6 @@ XX +2743+08519 Asia/Kathmandu Nepal
#
# +06
XX +2343+09025 Asia/Dhaka Russia; Kyrgyzstan; Bhutan; Bangladesh; Chagos
-# +06 until 2024-03-01; then +05
-XX +4315+07657 Asia/Almaty Kazakhstan (except western areas)
#
# +06:30
XX +1647+09610 Asia/Yangon Myanmar; Cocos
diff --git a/lib/tzdata/zones b/lib/tzdata/zones
index b054f010..3c4a951d 100644
--- a/lib/tzdata/zones
+++ b/lib/tzdata/zones
@@ -159,7 +159,6 @@ Asia/Barnaul
Asia/Beirut
Asia/Bishkek
Asia/Chita
-Asia/Choibalsan
Asia/Colombo
Asia/Damascus
Asia/Dhaka
@@ -239,11 +238,6 @@ Australia/Lord_Howe
Australia/Melbourne
Australia/Perth
Australia/Sydney
-CET
-CST6CDT
-EET
-EST
-EST5EDT
Etc/GMT
Etc/GMT+1
Etc/GMT+10
@@ -311,14 +305,9 @@ Europe/Volgograd
Europe/Warsaw
Europe/Zurich
Factory
-HST
Indian/Chagos
Indian/Maldives
Indian/Mauritius
-MET
-MST
-MST7MDT
-PST8PDT
Pacific/Apia
Pacific/Auckland
Pacific/Bougainville
@@ -349,7 +338,6 @@ Pacific/Rarotonga
Pacific/Tahiti
Pacific/Tarawa
Pacific/Tongatapu
-WET
GMT
Australia/ACT
Australia/LHI
@@ -365,6 +353,8 @@ Brazil/Acre
Brazil/DeNoronha
Brazil/East
Brazil/West
+CET
+CST6CDT
Canada/Atlantic
Canada/Central
Canada/Eastern
@@ -376,6 +366,9 @@ Canada/Yukon
Chile/Continental
Chile/EasterIsland
Cuba
+EET
+EST
+EST5EDT
Egypt
Eire
Etc/GMT+0
@@ -399,6 +392,9 @@ Jamaica
Japan
Kwajalein
Libya
+MET
+MST
+MST7MDT
Mexico/BajaNorte
Mexico/BajaSur
Mexico/General
@@ -562,6 +558,7 @@ America/Shiprock
America/Thunder_Bay
America/Yellowknife
Antarctica/South_Pole
+Asia/Choibalsan
Asia/Chongqing
Asia/Harbin
Asia/Kashgar
@@ -576,6 +573,7 @@ Europe/Zaporozhye
Pacific/Enderbury
Pacific/Johnston
Pacific/Yap
+WET
Africa/Asmera
America/Godthab
Asia/Ashkhabad
@@ -593,5 +591,7 @@ Asia/Ulan_Bator
Atlantic/Faeroe
Europe/Kiev
Europe/Nicosia
+HST
+PST8PDT
Pacific/Ponape
Pacific/Truk
diff --git a/lib/xmltodict.py b/lib/xmltodict.py
index ca760aa6..098f6276 100644
--- a/lib/xmltodict.py
+++ b/lib/xmltodict.py
@@ -1,19 +1,10 @@
#!/usr/bin/env python
"Makes working with XML feel like you are working with JSON"
-try:
- from defusedexpat import pyexpat as expat
-except ImportError:
- from xml.parsers import expat
+from xml.parsers import expat
from xml.sax.saxutils import XMLGenerator
from xml.sax.xmlreader import AttributesImpl
-try: # pragma no cover
- from cStringIO import StringIO
-except ImportError: # pragma no cover
- try:
- from StringIO import StringIO
- except ImportError:
- from io import StringIO
+from io import StringIO
_dict = dict
import platform
@@ -22,17 +13,8 @@ if tuple(map(int, platform.python_version_tuple()[:2])) < (3, 7):
from inspect import isgenerator
-try: # pragma no cover
- _basestring = basestring
-except NameError: # pragma no cover
- _basestring = str
-try: # pragma no cover
- _unicode = unicode
-except NameError: # pragma no cover
- _unicode = str
-
__author__ = 'Martin Blech'
-__version__ = '0.13.0'
+__version__ = "0.14.2"
__license__ = 'MIT'
@@ -40,7 +22,7 @@ class ParsingInterrupted(Exception):
pass
-class _DictSAXHandler(object):
+class _DictSAXHandler:
def __init__(self,
item_depth=0,
item_callback=lambda *args: True,
@@ -107,7 +89,7 @@ class _DictSAXHandler(object):
attrs['xmlns'] = self.namespace_declarations
self.namespace_declarations = self.dict_constructor()
self.path.append((name, attrs or None))
- if len(self.path) > self.item_depth:
+ if len(self.path) >= self.item_depth:
self.stack.append((self.item, self.data))
if self.xml_attribs:
attr_entries = []
@@ -135,7 +117,7 @@ class _DictSAXHandler(object):
should_continue = self.item_callback(self.path, item)
if not should_continue:
- raise ParsingInterrupted()
+ raise ParsingInterrupted
if self.stack:
data = (None if not self.data
else self.cdata_separator.join(self.data))
@@ -335,9 +317,8 @@ def parse(xml_input, encoding=None, expat=expat, process_namespaces=False,
"""
handler = _DictSAXHandler(namespace_separator=namespace_separator,
**kwargs)
- if isinstance(xml_input, _unicode):
- if not encoding:
- encoding = 'utf-8'
+ if isinstance(xml_input, str):
+ encoding = encoding or 'utf-8'
xml_input = xml_input.encode(encoding)
if not process_namespaces:
namespace_separator = None
@@ -372,8 +353,8 @@ def parse(xml_input, encoding=None, expat=expat, process_namespaces=False,
parser.ParseFile(xml_input)
elif isgenerator(xml_input):
for chunk in xml_input:
- parser.Parse(chunk,False)
- parser.Parse(b'',True)
+ parser.Parse(chunk, False)
+ parser.Parse(b'', True)
else:
parser.Parse(xml_input, True)
return handler.item
@@ -412,9 +393,7 @@ def _emit(key, value, content_handler,
if result is None:
return
key, value = result
- if (not hasattr(value, '__iter__')
- or isinstance(value, _basestring)
- or isinstance(value, dict)):
+ if not hasattr(value, '__iter__') or isinstance(value, (str, dict)):
value = [value]
for index, v in enumerate(value):
if full_document and depth == 0 and index > 0:
@@ -422,16 +401,13 @@ def _emit(key, value, content_handler,
if v is None:
v = _dict()
elif isinstance(v, bool):
- if v:
- v = _unicode('true')
- else:
- v = _unicode('false')
- elif not isinstance(v, dict):
- if expand_iter and hasattr(v, '__iter__') and not isinstance(v, _basestring):
+ v = 'true' if v else 'false'
+ elif not isinstance(v, (dict, str)):
+ if expand_iter and hasattr(v, '__iter__'):
v = _dict(((expand_iter, v),))
else:
- v = _unicode(v)
- if isinstance(v, _basestring):
+ v = str(v)
+ if isinstance(v, str):
v = _dict(((cdata_key, v),))
cdata = None
attrs = _dict()
@@ -445,14 +421,16 @@ def _emit(key, value, content_handler,
attr_prefix)
if ik == '@xmlns' and isinstance(iv, dict):
for k, v in iv.items():
- attr = 'xmlns{}'.format(':{}'.format(k) if k else '')
- attrs[attr] = _unicode(v)
+ attr = 'xmlns{}'.format(f':{k}' if k else '')
+ attrs[attr] = str(v)
continue
- if not isinstance(iv, _unicode):
- iv = _unicode(iv)
+ if not isinstance(iv, str):
+ iv = str(iv)
attrs[ik[len(attr_prefix):]] = iv
continue
children.append((ik, iv))
+ if isinstance(indent, int):
+ indent = ' ' * indent
if pretty:
content_handler.ignorableWhitespace(depth * indent)
content_handler.startElement(key, AttributesImpl(attrs))
diff --git a/lib/zipp.py b/lib/zipp.py
deleted file mode 100644
index 52c82a0e..00000000
--- a/lib/zipp.py
+++ /dev/null
@@ -1,312 +0,0 @@
-import io
-import posixpath
-import zipfile
-import itertools
-import contextlib
-import pathlib
-
-
-__all__ = ['Path']
-
-
-def _parents(path):
- """
- Given a path with elements separated by
- posixpath.sep, generate all parents of that path.
-
- >>> list(_parents('b/d'))
- ['b']
- >>> list(_parents('/b/d/'))
- ['/b']
- >>> list(_parents('b/d/f/'))
- ['b/d', 'b']
- >>> list(_parents('b'))
- []
- >>> list(_parents(''))
- []
- """
- return itertools.islice(_ancestry(path), 1, None)
-
-
-def _ancestry(path):
- """
- Given a path with elements separated by
- posixpath.sep, generate all elements of that path
-
- >>> list(_ancestry('b/d'))
- ['b/d', 'b']
- >>> list(_ancestry('/b/d/'))
- ['/b/d', '/b']
- >>> list(_ancestry('b/d/f/'))
- ['b/d/f', 'b/d', 'b']
- >>> list(_ancestry('b'))
- ['b']
- >>> list(_ancestry(''))
- []
- """
- path = path.rstrip(posixpath.sep)
- while path and path != posixpath.sep:
- yield path
- path, tail = posixpath.split(path)
-
-
-_dedupe = dict.fromkeys
-"""Deduplicate an iterable in original order"""
-
-
-def _difference(minuend, subtrahend):
- """
- Return items in minuend not in subtrahend, retaining order
- with O(1) lookup.
- """
- return itertools.filterfalse(set(subtrahend).__contains__, minuend)
-
-
-class CompleteDirs(zipfile.ZipFile):
- """
- A ZipFile subclass that ensures that implied directories
- are always included in the namelist.
- """
-
- @staticmethod
- def _implied_dirs(names):
- parents = itertools.chain.from_iterable(map(_parents, names))
- as_dirs = (p + posixpath.sep for p in parents)
- return _dedupe(_difference(as_dirs, names))
-
- def namelist(self):
- names = super(CompleteDirs, self).namelist()
- return names + list(self._implied_dirs(names))
-
- def _name_set(self):
- return set(self.namelist())
-
- def resolve_dir(self, name):
- """
- If the name represents a directory, return that name
- as a directory (with the trailing slash).
- """
- names = self._name_set()
- dirname = name + '/'
- dir_match = name not in names and dirname in names
- return dirname if dir_match else name
-
- @classmethod
- def make(cls, source):
- """
- Given a source (filename or zipfile), return an
- appropriate CompleteDirs subclass.
- """
- if isinstance(source, CompleteDirs):
- return source
-
- if not isinstance(source, zipfile.ZipFile):
- return cls(source)
-
- # Only allow for FastLookup when supplied zipfile is read-only
- if 'r' not in source.mode:
- cls = CompleteDirs
-
- source.__class__ = cls
- return source
-
-
-class FastLookup(CompleteDirs):
- """
- ZipFile subclass to ensure implicit
- dirs exist and are resolved rapidly.
- """
-
- def namelist(self):
- with contextlib.suppress(AttributeError):
- return self.__names
- self.__names = super(FastLookup, self).namelist()
- return self.__names
-
- def _name_set(self):
- with contextlib.suppress(AttributeError):
- return self.__lookup
- self.__lookup = super(FastLookup, self)._name_set()
- return self.__lookup
-
-
-class Path:
- """
- A pathlib-compatible interface for zip files.
-
- Consider a zip file with this structure::
-
- .
- ├── a.txt
- └── b
- ├── c.txt
- └── d
- └── e.txt
-
- >>> data = io.BytesIO()
- >>> zf = zipfile.ZipFile(data, 'w')
- >>> zf.writestr('a.txt', 'content of a')
- >>> zf.writestr('b/c.txt', 'content of c')
- >>> zf.writestr('b/d/e.txt', 'content of e')
- >>> zf.filename = 'mem/abcde.zip'
-
- Path accepts the zipfile object itself or a filename
-
- >>> root = Path(zf)
-
- From there, several path operations are available.
-
- Directory iteration (including the zip file itself):
-
- >>> a, b = root.iterdir()
- >>> a
- Path('mem/abcde.zip', 'a.txt')
- >>> b
- Path('mem/abcde.zip', 'b/')
-
- name property:
-
- >>> b.name
- 'b'
-
- join with divide operator:
-
- >>> c = b / 'c.txt'
- >>> c
- Path('mem/abcde.zip', 'b/c.txt')
- >>> c.name
- 'c.txt'
-
- Read text:
-
- >>> c.read_text()
- 'content of c'
-
- existence:
-
- >>> c.exists()
- True
- >>> (b / 'missing.txt').exists()
- False
-
- Coercion to string:
-
- >>> import os
- >>> str(c).replace(os.sep, posixpath.sep)
- 'mem/abcde.zip/b/c.txt'
-
- At the root, ``name``, ``filename``, and ``parent``
- resolve to the zipfile. Note these attributes are not
- valid and will raise a ``ValueError`` if the zipfile
- has no filename.
-
- >>> root.name
- 'abcde.zip'
- >>> str(root.filename).replace(os.sep, posixpath.sep)
- 'mem/abcde.zip'
- >>> str(root.parent)
- 'mem'
- """
-
- __repr = "{self.__class__.__name__}({self.root.filename!r}, {self.at!r})"
-
- def __init__(self, root, at=""):
- """
- Construct a Path from a ZipFile or filename.
-
- Note: When the source is an existing ZipFile object,
- its type (__class__) will be mutated to a
- specialized type. If the caller wishes to retain the
- original type, the caller should either create a
- separate ZipFile object or pass a filename.
- """
- self.root = FastLookup.make(root)
- self.at = at
-
- def open(self, mode='r', *args, pwd=None, **kwargs):
- """
- Open this entry as text or binary following the semantics
- of ``pathlib.Path.open()`` by passing arguments through
- to io.TextIOWrapper().
- """
- if self.is_dir():
- raise IsADirectoryError(self)
- zip_mode = mode[0]
- if not self.exists() and zip_mode == 'r':
- raise FileNotFoundError(self)
- stream = self.root.open(self.at, zip_mode, pwd=pwd)
- if 'b' in mode:
- if args or kwargs:
- raise ValueError("encoding args invalid for binary operation")
- return stream
- return io.TextIOWrapper(stream, *args, **kwargs)
-
- @property
- def name(self):
- return pathlib.Path(self.at).name or self.filename.name
-
- @property
- def suffix(self):
- return pathlib.Path(self.at).suffix or self.filename.suffix
-
- @property
- def suffixes(self):
- return pathlib.Path(self.at).suffixes or self.filename.suffixes
-
- @property
- def stem(self):
- return pathlib.Path(self.at).stem or self.filename.stem
-
- @property
- def filename(self):
- return pathlib.Path(self.root.filename).joinpath(self.at)
-
- def read_text(self, *args, **kwargs):
- with self.open('r', *args, **kwargs) as strm:
- return strm.read()
-
- def read_bytes(self):
- with self.open('rb') as strm:
- return strm.read()
-
- def _is_child(self, path):
- return posixpath.dirname(path.at.rstrip("/")) == self.at.rstrip("/")
-
- def _next(self, at):
- return self.__class__(self.root, at)
-
- def is_dir(self):
- return not self.at or self.at.endswith("/")
-
- def is_file(self):
- return self.exists() and not self.is_dir()
-
- def exists(self):
- return self.at in self.root._name_set()
-
- def iterdir(self):
- if not self.is_dir():
- raise ValueError("Can't listdir a file")
- subs = map(self._next, self.root.namelist())
- return filter(self._is_child, subs)
-
- def __str__(self):
- return posixpath.join(self.root.filename, self.at)
-
- def __repr__(self):
- return self.__repr.format(self=self)
-
- def joinpath(self, *other):
- next = posixpath.join(self.at, *other)
- return self._next(self.root.resolve_dir(next))
-
- __truediv__ = joinpath
-
- @property
- def parent(self):
- if not self.at:
- return self.filename.parent
- parent_at = posixpath.dirname(self.at.rstrip('/'))
- if parent_at:
- parent_at += '/'
- return self._next(parent_at)
diff --git a/lib/zipp/__init__.py b/lib/zipp/__init__.py
index d65297b8..031d9d4f 100644
--- a/lib/zipp/__init__.py
+++ b/lib/zipp/__init__.py
@@ -1,16 +1,27 @@
+"""
+A Path-like interface for zipfiles.
+
+This codebase is shared between zipfile.Path in the stdlib
+and zipp in PyPI. See
+https://github.com/python/importlib_metadata/wiki/Development-Methodology
+for more detail.
+"""
+
+import functools
import io
-import posixpath
-import zipfile
import itertools
-import contextlib
import pathlib
+import posixpath
import re
import stat
import sys
+import zipfile
from .compat.py310 import text_encoding
from .glob import Translator
+from ._functools import save_method_args
+
__all__ = ['Path']
@@ -37,7 +48,7 @@ def _parents(path):
def _ancestry(path):
"""
Given a path with elements separated by
- posixpath.sep, generate all elements of that path
+ posixpath.sep, generate all elements of that path.
>>> list(_ancestry('b/d'))
['b/d', 'b']
@@ -49,9 +60,14 @@ def _ancestry(path):
['b']
>>> list(_ancestry(''))
[]
+
+ Multiple separators are treated like a single.
+
+ >>> list(_ancestry('//b//d///f//'))
+ ['//b//d///f', '//b//d', '//b']
"""
path = path.rstrip(posixpath.sep)
- while path and path != posixpath.sep:
+ while path.rstrip(posixpath.sep):
yield path
path, tail = posixpath.split(path)
@@ -73,82 +89,19 @@ class InitializedState:
Mix-in to save the initialization state for pickling.
"""
+ @save_method_args
def __init__(self, *args, **kwargs):
- self.__args = args
- self.__kwargs = kwargs
super().__init__(*args, **kwargs)
def __getstate__(self):
- return self.__args, self.__kwargs
+ return self._saved___init__.args, self._saved___init__.kwargs
def __setstate__(self, state):
args, kwargs = state
super().__init__(*args, **kwargs)
-class SanitizedNames:
- """
- ZipFile mix-in to ensure names are sanitized.
- """
-
- def namelist(self):
- return list(map(self._sanitize, super().namelist()))
-
- @staticmethod
- def _sanitize(name):
- r"""
- Ensure a relative path with posix separators and no dot names.
-
- Modeled after
- https://github.com/python/cpython/blob/bcc1be39cb1d04ad9fc0bd1b9193d3972835a57c/Lib/zipfile/__init__.py#L1799-L1813
- but provides consistent cross-platform behavior.
-
- >>> san = SanitizedNames._sanitize
- >>> san('/foo/bar')
- 'foo/bar'
- >>> san('//foo.txt')
- 'foo.txt'
- >>> san('foo/.././bar.txt')
- 'foo/bar.txt'
- >>> san('foo../.bar.txt')
- 'foo../.bar.txt'
- >>> san('\\foo\\bar.txt')
- 'foo/bar.txt'
- >>> san('D:\\foo.txt')
- 'D/foo.txt'
- >>> san('\\\\server\\share\\file.txt')
- 'server/share/file.txt'
- >>> san('\\\\?\\GLOBALROOT\\Volume3')
- '?/GLOBALROOT/Volume3'
- >>> san('\\\\.\\PhysicalDrive1\\root')
- 'PhysicalDrive1/root'
-
- Retain any trailing slash.
- >>> san('abc/')
- 'abc/'
-
- Raises a ValueError if the result is empty.
- >>> san('../..')
- Traceback (most recent call last):
- ...
- ValueError: Empty filename
- """
-
- def allowed(part):
- return part and part not in {'..', '.'}
-
- # Remove the drive letter.
- # Don't use ntpath.splitdrive, because that also strips UNC paths
- bare = re.sub('^([A-Z]):', r'\1', name, flags=re.IGNORECASE)
- clean = bare.replace('\\', '/')
- parts = clean.split('/')
- joined = '/'.join(filter(allowed, parts))
- if not joined:
- raise ValueError("Empty filename")
- return joined + '/' * name.endswith('/')
-
-
-class CompleteDirs(InitializedState, SanitizedNames, zipfile.ZipFile):
+class CompleteDirs(InitializedState, zipfile.ZipFile):
"""
A ZipFile subclass that ensures that implied directories
are always included in the namelist.
@@ -230,16 +183,18 @@ class FastLookup(CompleteDirs):
"""
def namelist(self):
- with contextlib.suppress(AttributeError):
- return self.__names
- self.__names = super().namelist()
- return self.__names
+ return self._namelist
+
+ @functools.cached_property
+ def _namelist(self):
+ return super().namelist()
def _name_set(self):
- with contextlib.suppress(AttributeError):
- return self.__lookup
- self.__lookup = super()._name_set()
- return self.__lookup
+ return self._name_set_prop
+
+ @functools.cached_property
+ def _name_set_prop(self):
+ return super()._name_set()
def _extract_text_encoding(encoding=None, *args, **kwargs):
@@ -329,7 +284,7 @@ class Path:
>>> str(path.parent)
'mem'
- If the zipfile has no filename, such attributes are not
+ If the zipfile has no filename, such attributes are not
valid and accessing them will raise an Exception.
>>> zf.filename = None
@@ -388,7 +343,7 @@ class Path:
if self.is_dir():
raise IsADirectoryError(self)
zip_mode = mode[0]
- if not self.exists() and zip_mode == 'r':
+ if zip_mode == 'r' and not self.exists():
raise FileNotFoundError(self)
stream = self.root.open(self.at, zip_mode, pwd=pwd)
if 'b' in mode:
@@ -470,8 +425,7 @@ class Path:
prefix = re.escape(self.at)
tr = Translator(seps='/')
matches = re.compile(prefix + tr.translate(pattern)).fullmatch
- names = (data.filename for data in self.root.filelist)
- return map(self._next, filter(matches, names))
+ return map(self._next, filter(matches, self.root.namelist()))
def rglob(self, pattern):
return self.glob(f'**/{pattern}')
diff --git a/lib/zipp/_functools.py b/lib/zipp/_functools.py
new file mode 100644
index 00000000..f75ae2b0
--- /dev/null
+++ b/lib/zipp/_functools.py
@@ -0,0 +1,20 @@
+import collections
+import functools
+
+
+# from jaraco.functools 4.0.2
+def save_method_args(method):
+ """
+ Wrap a method such that when it is called, the args and kwargs are
+ saved on the method.
+ """
+ args_and_kwargs = collections.namedtuple('args_and_kwargs', 'args kwargs')
+
+ @functools.wraps(method)
+ def wrapper(self, /, *args, **kwargs):
+ attr_name = '_saved_' + method.__name__
+ attr = args_and_kwargs(args, kwargs)
+ setattr(self, attr_name, attr)
+ return method(self, *args, **kwargs)
+
+ return wrapper
diff --git a/lib/zipp/compat/overlay.py b/lib/zipp/compat/overlay.py
new file mode 100644
index 00000000..5a97ee7c
--- /dev/null
+++ b/lib/zipp/compat/overlay.py
@@ -0,0 +1,37 @@
+"""
+Expose zipp.Path as .zipfile.Path.
+
+Includes everything else in ``zipfile`` to match future usage. Just
+use:
+
+>>> from zipp.compat.overlay import zipfile
+
+in place of ``import zipfile``.
+
+Relative imports are supported too.
+
+>>> from zipp.compat.overlay.zipfile import ZipInfo
+
+The ``zipfile`` object added to ``sys.modules`` needs to be
+hashable (#126).
+
+>>> _ = hash(sys.modules['zipp.compat.overlay.zipfile'])
+"""
+
+import importlib
+import sys
+import types
+
+import zipp
+
+
+class HashableNamespace(types.SimpleNamespace):
+ def __hash__(self):
+ return hash(tuple(vars(self)))
+
+
+zipfile = HashableNamespace(**vars(importlib.import_module('zipfile')))
+zipfile.Path = zipp.Path
+zipfile._path = zipp
+
+sys.modules[__name__ + '.zipfile'] = zipfile # type: ignore[assignment]
diff --git a/lib/zipp/compat/py310.py b/lib/zipp/compat/py310.py
index d5ca53e0..e1e7ec22 100644
--- a/lib/zipp/compat/py310.py
+++ b/lib/zipp/compat/py310.py
@@ -1,5 +1,5 @@
-import sys
import io
+import sys
def _text_encoding(encoding, stacklevel=2, /): # pragma: no cover
@@ -7,5 +7,7 @@ def _text_encoding(encoding, stacklevel=2, /): # pragma: no cover
text_encoding = (
- io.text_encoding if sys.version_info > (3, 10) else _text_encoding # type: ignore
+ io.text_encoding # type: ignore[unused-ignore, attr-defined]
+ if sys.version_info > (3, 10)
+ else _text_encoding
)
diff --git a/lib/zipp/glob.py b/lib/zipp/glob.py
index 69c41d77..4ed74cc4 100644
--- a/lib/zipp/glob.py
+++ b/lib/zipp/glob.py
@@ -1,7 +1,6 @@
import os
import re
-
_default_seps = os.sep + str(os.altsep) * bool(os.altsep)
@@ -28,7 +27,7 @@ class Translator:
"""
Given a glob pattern, produce a regex that matches it.
"""
- return self.extend(self.translate_core(pattern))
+ return self.extend(self.match_dirs(self.translate_core(pattern)))
def extend(self, pattern):
r"""
@@ -41,6 +40,14 @@ class Translator:
"""
return rf'(?s:{pattern})\Z'
+ def match_dirs(self, pattern):
+ """
+ Ensure that zipfile.Path directory names are matched.
+
+ zipfile.Path directory names always end in a slash.
+ """
+ return rf'{pattern}[/]?'
+
def translate_core(self, pattern):
r"""
Given a glob pattern, produce a regex that matches it.
diff --git a/package/Tautulli.nsi b/package/Tautulli.nsi
index ad09846c..7232c23f 100644
--- a/package/Tautulli.nsi
+++ b/package/Tautulli.nsi
@@ -7,7 +7,7 @@
!define APP_NAME "Tautulli"
!define COMP_NAME "Tautulli"
!define WEB_SITE "https://tautulli.com"
-!define COPYRIGHT "Tautulli © 2020"
+!define COPYRIGHT "Tautulli © 2025"
!define DESCRIPTION "Monitor your Plex Media Server"
!define APP_ICON "..\dist\Tautulli\data\interfaces\default\images\logo-circle.ico"
!define LICENSE_TXT "..\dist\Tautulli\LICENSE"
diff --git a/package/requirements-package.txt b/package/requirements-package.txt
index 9ac6fba1..5837f631 100644
--- a/package/requirements-package.txt
+++ b/package/requirements-package.txt
@@ -1,11 +1,11 @@
apscheduler==3.10.1
-cryptography==43.0.0
-importlib-metadata==8.2.0
-importlib-resources==6.4.0
-pyinstaller==6.8.0
-pyopenssl==24.2.1
+cryptography==44.0.2
+importlib-metadata==8.5.0
+importlib-resources==6.4.5
+pyinstaller==6.10.0
+pyopenssl==25.0.0
pyobjc-core==10.3.1; platform_system == "Darwin"
pyobjc-framework-Cocoa==10.3.1; platform_system == "Darwin"
-pywin32==306; platform_system == "Windows"
+pywin32==308; platform_system == "Windows"
diff --git a/plexpy/__init__.py b/plexpy/__init__.py
index 0c782752..cafc0127 100644
--- a/plexpy/__init__.py
+++ b/plexpy/__init__.py
@@ -845,7 +845,7 @@ def dbcheck():
"timestamp INTEGER, section_id INTEGER, user_id INTEGER, rating_key INTEGER, media_type TEXT, "
"title TEXT, file_format TEXT, "
"metadata_level INTEGER, media_info_level INTEGER, "
- "thumb_level INTEGER DEFAULT 0, art_level INTEGER DEFAULT 0, "
+ "thumb_level INTEGER DEFAULT 0, art_level INTEGER DEFAULT 0, logo_level INTEGER DEFAULT 0, "
"custom_fields TEXT, individual_files INTEGER DEFAULT 0, "
"file_size INTEGER DEFAULT 0, complete INTEGER DEFAULT 0, "
"exported_items INTEGER DEFAULT 0, total_items INTEGER DEFAULT 0)"
@@ -2589,6 +2589,15 @@ def dbcheck():
"ALTER TABLE exports ADD COLUMN total_items INTEGER DEFAULT 0"
)
+ # Upgrade exports table from earlier versions
+ try:
+ c_db.execute("SELECT logo_level FROM exports")
+ except sqlite3.OperationalError:
+ logger.debug("Altering database. Updating database table exports.")
+ c_db.execute(
+ "ALTER TABLE exports ADD COLUMN logo_level INTEGER DEFAULT 0"
+ )
+
# Fix unique constraints
try:
c_db.execute("DELETE FROM tvmaze_lookup "
diff --git a/plexpy/activity_handler.py b/plexpy/activity_handler.py
index 2758133b..8c10b922 100644
--- a/plexpy/activity_handler.py
+++ b/plexpy/activity_handler.py
@@ -314,6 +314,10 @@ class ActivityHandler(object):
if self.metadata:
this_guid = self.metadata['guid']
+ # Check for stream offset notifications
+ self.check_markers()
+ self.check_watched()
+
# Make sure the same item is being played
if (self.rating_key == last_rating_key
or self.rating_key == last_rating_key_websocket
@@ -354,10 +358,6 @@ class ActivityHandler(object):
self.on_stop(force_stop=True)
self.on_start()
- # Check for stream offset notifications
- self.check_markers()
- self.check_watched()
-
def check_markers(self):
# Monitor if the stream has reached the intro or credit marker offsets
self.get_metadata()
diff --git a/plexpy/activity_pinger.py b/plexpy/activity_pinger.py
index 9e8487fb..22688027 100644
--- a/plexpy/activity_pinger.py
+++ b/plexpy/activity_pinger.py
@@ -173,7 +173,7 @@ def check_active_sessions(ws_request=False):
row_id = monitor_process.write_session_history(session=stream)
if row_id:
- # If session is written to the databaase successfully, remove the session from the session table
+ # If session is written to the database successfully, remove the session from the session table
logger.debug("Tautulli Monitor :: Removing sessionKey %s ratingKey %s from session queue"
% (stream['session_key'], stream['rating_key']))
monitor_process.delete_session(row_id=row_id)
diff --git a/plexpy/common.py b/plexpy/common.py
index 59c8aeaa..d057cee9 100644
--- a/plexpy/common.py
+++ b/plexpy/common.py
@@ -476,6 +476,7 @@ NOTIFICATION_PARAMETERS = [
{'name': 'Stream Audio Sample Rate', 'type': 'int', 'value': 'stream_audio_sample_rate', 'description': 'The audio sample rate (in Hz) of the stream.'},
{'name': 'Stream Audio Language', 'type': 'str', 'value': 'stream_audio_language', 'description': 'The audio language of the stream.'},
{'name': 'Stream Audio Language Code', 'type': 'str', 'value': 'stream_audio_language_code', 'description': 'The audio language code of the stream.'},
+ {'name': 'Stream Audio Profile', 'type': 'str', 'value': 'stream_audio_profile', 'description': 'The audio profile of the stream.'},
{'name': 'Stream Subtitle Codec', 'type': 'str', 'value': 'stream_subtitle_codec', 'description': 'The subtitle codec of the stream.'},
{'name': 'Stream Subtitle Container', 'type': 'str', 'value': 'stream_subtitle_container', 'description': 'The subtitle container of the stream.'},
{'name': 'Stream Subtitle Format', 'type': 'str', 'value': 'stream_subtitle_format', 'description': 'The subtitle format of the stream.'},
@@ -557,6 +558,8 @@ NOTIFICATION_PARAMETERS = [
{'name': 'Poster URL', 'type': 'str', 'value': 'poster_url', 'description': 'A URL for the movie, TV show, or album poster.'},
{'name': 'Plex ID', 'type': 'str', 'value': 'plex_id', 'description': 'The Plex ID for the item.', 'example': 'e.g. 5d7769a9594b2b001e6a6b7e'},
{'name': 'Plex URL', 'type': 'str', 'value': 'plex_url', 'description': 'The Plex URL to your server for the item.'},
+ {'name': 'Plex Slug', 'type': 'str', 'value': 'plex_slug', 'description': 'The Plex URL slug for the item.'},
+ {'name': 'Plex Watch URL', 'type': 'str', 'value': 'plex_watch_url', 'description': 'The Plex URL to watch.plex.tv for the item.'},
{'name': 'IMDB ID', 'type': 'str', 'value': 'imdb_id', 'description': 'The IMDB ID for the movie or TV show.', 'example': 'e.g. tt2488496'},
{'name': 'IMDB URL', 'type': 'str', 'value': 'imdb_url', 'description': 'The IMDB URL for the movie or TV show.'},
{'name': 'TVDB ID', 'type': 'int', 'value': 'thetvdb_id', 'description': 'The TVDB ID for the movie or TV show.', 'example': 'e.g. 121361'},
@@ -604,6 +607,7 @@ NOTIFICATION_PARAMETERS = [
{'name': 'Audio Sample Rate', 'type': 'int', 'value': 'audio_sample_rate', 'description': 'The audio sample rate (in Hz) of the original media.'},
{'name': 'Audio Language', 'type': 'str', 'value': 'audio_language', 'description': 'The audio language of the original media.'},
{'name': 'Audio Language Code', 'type': 'str', 'value': 'audio_language_code', 'description': 'The audio language code of the original media.'},
+ {'name': 'Audio Profile', 'type': 'str', 'value': 'audio_profile', 'description': 'The audio profile of the original media.'},
{'name': 'Subtitle Codec', 'type': 'str', 'value': 'subtitle_codec', 'description': 'The subtitle codec of the original media.'},
{'name': 'Subtitle Container', 'type': 'str', 'value': 'subtitle_container', 'description': 'The subtitle container of the original media.'},
{'name': 'Subtitle Format', 'type': 'str', 'value': 'subtitle_format', 'description': 'The subtitle format of the original media.'},
diff --git a/plexpy/config.py b/plexpy/config.py
index c41e3b59..3e9862ff 100644
--- a/plexpy/config.py
+++ b/plexpy/config.py
@@ -568,7 +568,7 @@ class Config(object):
def _upgrade(self):
"""
- Upgrades config file from previous verisions and bumps up config version
+ Upgrades config file from previous versions and bumps up config version
"""
if self.CONFIG_VERSION == 0:
self.CONFIG_VERSION = 1
diff --git a/plexpy/datatables.py b/plexpy/datatables.py
index 68c76c57..0cc94760 100644
--- a/plexpy/datatables.py
+++ b/plexpy/datatables.py
@@ -283,7 +283,7 @@ def extract_columns(columns=None, match_columns=None):
columns_string = columns_string.rstrip(', ')
# We return a dict of the column params
- # column_string is a comma seperated list of the exact column variables received.
+ # column_string is a comma separated list of the exact column variables received.
# column_literal is the text before the "as" if we have an "as". Usually a function.
# column_named is the text after the "as", if we have an "as". Any table prefix is also stripped off.
# We use this to match with columns received from the Datatables request.
diff --git a/plexpy/exporter.py b/plexpy/exporter.py
index 08ea1176..18c20a4e 100644
--- a/plexpy/exporter.py
+++ b/plexpy/exporter.py
@@ -36,20 +36,20 @@ from plexpy.plex import Plex
class Export(object):
- # True/False for allowed (thumb, art) image export
+ # True/False for allowed (thumb, art, logo) image export
MEDIA_TYPES = {
- 'movie': (True, True),
- 'show': (True, True),
- 'season': (True, True),
- 'episode': (False, False),
- 'artist': (True, True),
- 'album': (True, True),
- 'track': (False, False),
- 'photoalbum': (False, False),
- 'photo': (False, False),
- 'clip': (False, False),
- 'collection': (True, True),
- 'playlist': (True, True)
+ 'movie': (True, True, True),
+ 'show': (True, True, True),
+ 'season': (True, True, True),
+ 'episode': (False, False, True),
+ 'artist': (True, True, False),
+ 'album': (True, True, False),
+ 'track': (False, False, False),
+ 'photoalbum': (False, False, False),
+ 'photo': (False, False, False),
+ 'clip': (False, False, False),
+ 'collection': (True, True, False),
+ 'playlist': (True, True, False)
}
PLURAL_MEDIA_TYPES = {
'movie': 'movies',
@@ -96,7 +96,7 @@ class Export(object):
def __init__(self, section_id=None, user_id=None, rating_key=None, file_format='csv',
metadata_level=1, media_info_level=1,
- thumb_level=0, art_level=0,
+ thumb_level=0, art_level=0, logo_level=0,
custom_fields='', export_type='all', individual_files=False):
self.section_id = helpers.cast_to_int(section_id) or None
self.user_id = helpers.cast_to_int(user_id) or None
@@ -106,6 +106,7 @@ class Export(object):
self.media_info_level = helpers.cast_to_int(media_info_level)
self.thumb_level = helpers.cast_to_int(thumb_level)
self.art_level = helpers.cast_to_int(art_level)
+ self.logo_level = helpers.cast_to_int(logo_level)
self.custom_fields = custom_fields.replace(' ', '')
self._custom_fields = {}
self.export_type = str(export_type).lower() or 'all'
@@ -124,6 +125,7 @@ class Export(object):
self.file_size = 0
self.exported_thumb = False
self.exported_art = False
+ self.exported_logo = False
self._reload_check_files = False
self.total_items = 0
@@ -136,6 +138,7 @@ class Export(object):
self.media_info_level = 1
self.thumb_level = 0
self.art_level = 0
+ self.logo_level = 0
self.custom_fields = ''
def return_attrs(self, media_type, flatten=False):
@@ -191,6 +194,7 @@ class Export(object):
},
'hasCreditsMarker': None,
'hasPreviewThumbnails': None,
+ 'hasVoiceActivity': None,
'key': None,
'labels': {
'id': None,
@@ -203,6 +207,9 @@ class Export(object):
'librarySectionKey': None,
'librarySectionTitle': None,
'locations': None,
+ 'logo': lambda o: next((i.url for i in o.images if i.type == 'clearLogo'), None),
+ 'logoFile': lambda o: self.get_image(o, 'logo'),
+ 'logoProvider': lambda o: self.get_image_provider(o, 'logo'),
'markers': {
'end': None,
'final': None,
@@ -223,6 +230,7 @@ class Export(object):
'id': None,
'isOptimizedVersion': None,
'has64bitOffsets': None,
+ 'hasVoiceActivity': None,
'optimizedForStreaming': None,
'proxyType': None,
'target': None,
@@ -334,6 +342,7 @@ class Export(object):
'streamIdentifier': None
},
'subtitleStreams': {
+ 'canAutoSync': None,
'codec': None,
'default': None,
'displayTitle': None,
@@ -451,6 +460,9 @@ class Export(object):
'librarySectionKey': None,
'librarySectionTitle': None,
'locations': None,
+ 'logo': lambda o: next((i.url for i in o.images if i.type == 'clearLogo'), None),
+ 'logoFile': lambda o: self.get_image(o, 'logo'),
+ 'logoProvider': lambda o: self.get_image_provider(o, 'logo'),
'metadataDirectory': None,
'network': None,
'originallyAvailableAt': partial(helpers.datetime_to_iso, to_date=True),
@@ -521,6 +533,9 @@ class Export(object):
'librarySectionID': None,
'librarySectionKey': None,
'librarySectionTitle': None,
+ 'logo': lambda o: next((i.url for i in o.images if i.type == 'clearLogo'), None),
+ 'logoFile': lambda o: self.get_image(o, 'logo'),
+ 'logoProvider': lambda o: self.get_image_provider(o, 'logo'),
'metadataDirectory': None,
'parentGuid': None,
'parentIndex': None,
@@ -601,6 +616,7 @@ class Export(object):
'hasCreditsMarker': None,
'hasIntroMarker': None,
'hasPreviewThumbnails': None,
+ 'hasVoiceActivity': None,
'index': None,
'key': None,
'labels': {
@@ -613,6 +629,9 @@ class Export(object):
'librarySectionKey': None,
'librarySectionTitle': None,
'locations': None,
+ 'logo': lambda o: next((i.url for i in o.images if i.type == 'clearLogo'), None),
+ 'logoFile': lambda o: self.get_image(o, 'logo'),
+ 'logoProvider': lambda o: self.get_image_provider(o, 'logo'),
'markers': {
'end': None,
'final': None,
@@ -633,6 +652,7 @@ class Export(object):
'id': None,
'isOptimizedVersion': None,
'has64bitOffsets': None,
+ 'hasVoiceActivity': None,
'optimizedForStreaming': None,
'proxyType': None,
'target': None,
@@ -744,6 +764,7 @@ class Export(object):
'streamIdentifier': None
},
'subtitleStreams': {
+ 'canAutoSync': None,
'codec': None,
'default': None,
'displayTitle': None,
@@ -1341,7 +1362,7 @@ class Export(object):
3: [
'art', 'thumb', 'key', 'chapterSource',
'chapters.tag', 'chapters.index', 'chapters.start', 'chapters.end', 'chapters.thumb',
- 'updatedAt', 'lastViewedAt', 'viewCount', 'lastRatedAt', 'hasPreviewThumbnails'
+ 'updatedAt', 'lastViewedAt', 'viewCount', 'lastRatedAt', 'hasPreviewThumbnails', 'hasVoiceActivity'
],
9: self._get_all_metadata_attrs(_media_type)
}
@@ -1454,7 +1475,7 @@ class Export(object):
3: [
'art', 'thumb', 'key', 'chapterSource',
'chapters.tag', 'chapters.index', 'chapters.start', 'chapters.end', 'chapters.thumb',
- 'updatedAt', 'lastViewedAt', 'viewCount', 'lastRatedAt', 'hasPreviewThumbnails',
+ 'updatedAt', 'lastViewedAt', 'viewCount', 'lastRatedAt', 'hasPreviewThumbnails', 'hasVoiceActivity',
'parentThumb', 'parentKey',
'grandparentArt', 'grandparentThumb', 'grandparentTheme', 'grandparentKey'
],
@@ -1773,6 +1794,8 @@ class Export(object):
msg = "Export called with invalid thumb_level '{}'.".format(self.thumb_level)
elif self.art_level not in self.IMAGE_LEVELS:
msg = "Export called with invalid art_level '{}'.".format(self.art_level)
+ elif self.logo_level not in self.IMAGE_LEVELS:
+ msg = "Export called with invalid logo_level '{}'.".format(self.logo_level)
elif self.file_format not in self.FILE_FORMATS:
msg = "Export called with invalid file_format '{}'.".format(self.file_format)
elif self.export_type not in self.EXPORT_TYPES:
@@ -1800,10 +1823,10 @@ class Export(object):
if self.rating_key:
logger.debug(
"Tautulli Exporter :: Export called with rating_key %s, "
- "metadata_level %d, media_info_level %d, thumb_level %s, art_level %s, "
+ "metadata_level %d, media_info_level %d, thumb_level %s, art_level %s, logo_level %s, "
"file_format %s",
self.rating_key, self.metadata_level, self.media_info_level,
- self.thumb_level, self.art_level, self.file_format)
+ self.thumb_level, self.art_level, self.logo_level, self.file_format)
self.obj = plex.get_item(self.rating_key)
self.media_type = self._media_type(self.obj)
@@ -1819,10 +1842,10 @@ class Export(object):
elif self.user_id:
logger.debug(
"Tautulli Exporter :: Export called with user_id %s, "
- "metadata_level %d, media_info_level %d, thumb_level %s, art_level %s, "
+ "metadata_level %d, media_info_level %d, thumb_level %s, art_level %s, logo_level %s, "
"export_type %s, file_format %s",
self.user_id, self.metadata_level, self.media_info_level,
- self.thumb_level, self.art_level, self.export_type, self.file_format)
+ self.thumb_level, self.art_level, self.logo_level, self.export_type, self.file_format)
self.obj = plex.PlexServer
self.media_type = self.export_type
@@ -1832,10 +1855,10 @@ class Export(object):
elif self.section_id:
logger.debug(
"Tautulli Exporter :: Export called with section_id %s, "
- "metadata_level %d, media_info_level %d, thumb_level %s, art_level %s, "
+ "metadata_level %d, media_info_level %d, thumb_level %s, art_level %s, logo_level %s, "
"export_type %s, file_format %s",
self.section_id, self.metadata_level, self.media_info_level,
- self.thumb_level, self.art_level, self.export_type, self.file_format)
+ self.thumb_level, self.art_level, self.logo_level, self.export_type, self.file_format)
self.obj = plex.get_library(self.section_id)
if self.export_type == 'all':
@@ -1859,6 +1882,8 @@ class Export(object):
self.thumb_level = 0
if not self.MEDIA_TYPES[self.media_type][1]:
self.art_level = 0
+ if not self.MEDIA_TYPES[self.media_type][2]:
+ self.logo_level = 0
self._process_custom_fields()
@@ -1892,6 +1917,7 @@ class Export(object):
'media_info_level': self.media_info_level,
'thumb_level': self.thumb_level,
'art_level': self.art_level,
+ 'logo_level': self.logo_level,
'custom_fields': self.custom_fields,
'individual_files': self.individual_files
}
@@ -1916,6 +1942,7 @@ class Export(object):
values = {
'thumb_level': self.thumb_level,
'art_level': self.art_level,
+ 'logo_level': self.logo_level,
'complete': complete,
'file_size': self.file_size
}
@@ -1971,6 +1998,7 @@ class Export(object):
self.thumb_level = self.thumb_level or 10 if self.exported_thumb else 0
self.art_level = self.art_level or 10 if self.exported_art else 0
+ self.logo_level = self.logo_level or 10 if self.exported_logo else 0
self.file_size += sum(item.file_size for item in items)
@@ -2037,6 +2065,8 @@ class Export(object):
self.exported_thumb = True
elif any(f.endswith('.art.jpg') for f in files):
self.exported_art = True
+ elif any(f.endswith('.logo.jpg') for f in files):
+ self.exported_logo = True
def _media_type(self, obj):
return 'photoalbum' if self.is_photoalbum(obj) else obj.type
@@ -2108,7 +2138,7 @@ class Export(object):
return media_type, field
def _get_all_metadata_attrs(self, media_type):
- exclude_attrs = ('locations', 'media', 'artFile', 'thumbFile')
+ exclude_attrs = ('locations', 'media', 'artFile', 'thumbFile', 'logoFile')
all_attrs = self.return_attrs(media_type)
return [attr for attr in all_attrs if attr not in exclude_attrs]
@@ -2133,6 +2163,9 @@ class Export(object):
if self.art_level:
if 'artFile' in media_attrs and self.MEDIA_TYPES[media_type][1]:
export_attrs_set.add('artFile')
+ if self.logo_level:
+ if 'logoFile' in media_attrs and self.MEDIA_TYPES[media_type][2]:
+ export_attrs_set.add('logoFile')
if media_type in self._custom_fields:
export_attrs_set.update(self._custom_fields[media_type])
@@ -2258,6 +2291,10 @@ class Export(object):
if not hasattr(item, '_arts'):
item._arts = item.arts()
return getattr(item, '_arts', [])
+ elif image == 'logo':
+ if not hasattr(item, '_logos'):
+ item._logos = item.logos()
+ return getattr(item, '_logos', [])
else:
if not hasattr(item, '_posters'):
item._posters = item.posters()
@@ -2272,13 +2309,13 @@ class Export(object):
rating_key = item.ratingKey
export_image = True
- if self.thumb_level == 1 or self.art_level == 1:
+ if self.thumb_level == 1 or self.art_level == 1 or self.logo_level == 1:
selected = self._get_selected_image(item, image)
export_image = selected and selected.ratingKey.startswith('upload://')
- elif self.thumb_level == 2 or self.art_level == 2:
+ elif self.thumb_level == 2 or self.art_level == 2 or self.logo_level == 2:
export_image = any(field.locked and field.name == image
for field in item.fields)
- elif self.thumb_level == 9 or self.art_level == 9:
+ elif self.thumb_level == 9 or self.art_level == 9 or self.logo_level == 9:
export_image = True
if not export_image and image + 'File' in self._custom_fields.get(media_type, set()):
@@ -2292,6 +2329,8 @@ class Export(object):
image_url = item.thumbUrl
elif image == 'art':
image_url = item.artUrl
+ elif image == 'logo':
+ image_url = item.logoUrl
if not image_url:
return
@@ -2344,7 +2383,7 @@ class ExportObject(Export):
def get_export(export_id):
db = database.MonitorDatabase()
- result = db.select_single("SELECT timestamp, title, file_format, thumb_level, art_level, "
+ result = db.select_single("SELECT timestamp, title, file_format, thumb_level, art_level, logo_level, "
"individual_files, complete "
"FROM exports WHERE id = ?",
[export_id])
@@ -2436,6 +2475,7 @@ def get_export_datatable(section_id=None, user_id=None, rating_key=None, kwargs=
"exports.media_info_level",
"exports.thumb_level",
"exports.art_level",
+ "exports.logo_level",
"exports.custom_fields",
"exports.individual_files",
"exports.file_size",
@@ -2481,6 +2521,7 @@ def get_export_datatable(section_id=None, user_id=None, rating_key=None, kwargs=
'media_info_level': item['media_info_level'],
'thumb_level': item['thumb_level'],
'art_level': item['art_level'],
+ 'logo_level': item['logo_level'],
'custom_fields': item['custom_fields'],
'individual_files': item['individual_files'],
'file_size': item['file_size'],
@@ -2628,7 +2669,7 @@ def build_export_docs():
sections = []
- for media_type, (thumb, art) in export.MEDIA_TYPES.items():
+ for media_type, (thumb, art, logo) in export.MEDIA_TYPES.items():
if media_type == 'photoalbum':
section_title = 'Photo Albums'
else:
@@ -2642,7 +2683,7 @@ def build_export_docs():
# Metadata Fields table
table_rows = []
for attr, level in sorted(metadata_levels_map.items(), key=helpers.sort_attrs):
- if thumb and attr == 'thumbFile' or art and attr == 'artFile':
+ if thumb and attr == 'thumbFile' or art and attr == 'artFile' or logo and attr == 'logoFile':
text = 'Refer to [Image Exports](#image-export)'
row = {
'attr': attr,
diff --git a/plexpy/graphs.py b/plexpy/graphs.py
index 70122aee..771b4eaf 100644
--- a/plexpy/graphs.py
+++ b/plexpy/graphs.py
@@ -138,6 +138,12 @@ class Graphs(object):
if libraries.has_library_type('live'):
series_output.append(series_4_output)
+ if len(series_output) > 0:
+ series_total = [sum(x) for x in zip(*[x['data'] for x in series_output])]
+ series_total_output = {'name': 'Total',
+ 'data': series_total}
+ series_output.append(series_total_output)
+
output = {'categories': categories,
'series': series_output}
return output
diff --git a/plexpy/helpers.py b/plexpy/helpers.py
index dfc82d25..fdb79830 100644
--- a/plexpy/helpers.py
+++ b/plexpy/helpers.py
@@ -24,8 +24,6 @@ from cloudinary.utils import cloudinary_url
from collections import OrderedDict
from datetime import date, datetime, timezone
from functools import reduce, wraps
-import hashlib
-import imghdr
from itertools import groupby
from future.moves.itertools import islice, zip_longest
from ipaddress import ip_address, ip_network, IPv4Address
@@ -943,39 +941,6 @@ def cloudinary_transform(rating_key=None, width=1000, height=1500, opacity=100,
return url
-def cache_image(url, image=None):
- """
- Saves an image to the cache directory.
- If no image is provided, tries to return the image from the cache directory.
- """
- # Create image directory if it doesn't exist
- imgdir = os.path.join(plexpy.CONFIG.CACHE_DIR, 'images/')
- if not os.path.exists(imgdir):
- logger.debug("Tautulli Helpers :: Creating image cache directory at %s" % imgdir)
- os.makedirs(imgdir)
-
- # Create a hash of the url to use as the filename
- imghash = hashlib.md5(url).hexdigest()
- imagefile = os.path.join(imgdir, imghash)
-
- # If an image is provided, save it to the cache directory
- if image:
- try:
- with open(imagefile, 'wb') as cache_file:
- cache_file.write(image)
- except IOError as e:
- logger.error("Tautulli Helpers :: Failed to cache image %s: %s" % (imagefile, e))
-
- # Try to return the image from the cache directory
- if os.path.isfile(imagefile):
- imagetype = 'image/' + imghdr.what(os.path.abspath(imagefile))
- else:
- imagefile = None
- imagetype = 'image/jpeg'
-
- return imagefile, imagetype
-
-
def build_datatables_json(kwargs, dt_columns, default_sort_col=None):
""" Builds datatables json data
diff --git a/plexpy/mobile_app.py b/plexpy/mobile_app.py
index 4d1267a1..8ba075d5 100644
--- a/plexpy/mobile_app.py
+++ b/plexpy/mobile_app.py
@@ -132,7 +132,7 @@ def set_mobile_device_config(mobile_device_id=None, **kwargs):
if str(mobile_device_id).isdigit():
mobile_device_id = int(mobile_device_id)
else:
- logger.error("Tautulli MobileApp :: Unable to set exisiting mobile device: invalid mobile_device_id %s." % mobile_device_id)
+ logger.error("Tautulli MobileApp :: Unable to set existing mobile device: invalid mobile_device_id %s." % mobile_device_id)
return False
keys = {'id': mobile_device_id}
@@ -198,11 +198,10 @@ def validate_onesignal_id(onesignal_id):
return 2
headers = {'Content-Type': 'application/json'}
- params = {'app_id': _ONESIGNAL_APP_ID}
logger.info("Tautulli MobileApp :: Validating OneSignal ID")
try:
- r = requests.get('https://onesignal.com/api/v1/players/{}'.format(onesignal_id), headers=headers, params=params)
+ r = requests.get(f'https://api.onesignal.com/apps/{_ONESIGNAL_APP_ID}/subscriptions/{onesignal_id}/user/identity', headers=headers)
status_code = r.status_code
logger.info("Tautulli MobileApp :: OneSignal ID validation returned status code %s", status_code)
return int(status_code == 200)
diff --git a/plexpy/newsletters.py b/plexpy/newsletters.py
index b49077a2..c44b505f 100644
--- a/plexpy/newsletters.py
+++ b/plexpy/newsletters.py
@@ -459,8 +459,12 @@ class Newsletter(object):
self.retrieve_data()
+ # Convert CustomArrow to string
+ from plexpy.notification_handler import CustomArrow
+ parameters = {k: str(v) if isinstance(v, CustomArrow) else v for k, v in self.parameters.items()}
+
return {'title': self.NAME,
- 'parameters': self.parameters,
+ 'parameters': parameters,
'data': self.data}
def generate_newsletter(self, preview=False):
diff --git a/plexpy/notification_handler.py b/plexpy/notification_handler.py
index e981b17b..0e30d6e2 100644
--- a/plexpy/notification_handler.py
+++ b/plexpy/notification_handler.py
@@ -684,23 +684,23 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m
thetvdb_media_type = 'movie' if notify_params['media_type'] == 'movie' else 'series'
notify_params['thetvdb_id'] = notify_params['thetvdb_id'] or notify_params['guid'].split('thetvdb://')[1].split('/')[0].split('?')[0]
notify_params['thetvdb_url'] = f'https://thetvdb.com/dereferrer/{thetvdb_media_type}/{notify_params["thetvdb_id"]}'
- notify_params['trakt_url'] = 'https://trakt.tv/search/tvdb/' + notify_params['thetvdb_id'] + '?type=show'
+ notify_params['trakt_url'] = 'https://trakt.tv/search/tvdb/' + notify_params['thetvdb_id'] + '?id_type=show'
elif 'thetvdbdvdorder://' in notify_params['guid']:
notify_params['thetvdb_id'] = notify_params['guid'].split('thetvdbdvdorder://')[1].split('/')[0].split('?')[0]
notify_params['thetvdb_url'] = f'https://thetvdb.com/dereferrer/series/{notify_params["thetvdb_id"]}'
- notify_params['trakt_url'] = 'https://trakt.tv/search/tvdb/' + notify_params['thetvdb_id'] + '?type=show'
+ notify_params['trakt_url'] = 'https://trakt.tv/search/tvdb/' + notify_params['thetvdb_id'] + '?id_type=show'
if 'themoviedb://' in notify_params['guid'] or notify_params['themoviedb_id']:
if notify_params['media_type'] == 'movie':
notify_params['themoviedb_id'] = notify_params['themoviedb_id'] or notify_params['guid'].split('themoviedb://')[1].split('?')[0]
notify_params['themoviedb_url'] = 'https://www.themoviedb.org/movie/' + notify_params['themoviedb_id']
- notify_params['trakt_url'] = 'https://trakt.tv/search/tmdb/' + notify_params['themoviedb_id'] + '?type=movie'
+ notify_params['trakt_url'] = 'https://trakt.tv/search/tmdb/' + notify_params['themoviedb_id'] + '?id_type=movie'
elif notify_params['media_type'] in ('show', 'season', 'episode'):
notify_params['themoviedb_id'] = notify_params['themoviedb_id'] or notify_params['guid'].split('themoviedb://')[1].split('/')[0].split('?')[0]
notify_params['themoviedb_url'] = 'https://www.themoviedb.org/tv/' + notify_params['themoviedb_id']
- notify_params['trakt_url'] = 'https://trakt.tv/search/tmdb/' + notify_params['themoviedb_id'] + '?type=show'
+ notify_params['trakt_url'] = 'https://trakt.tv/search/tmdb/' + notify_params['themoviedb_id'] + '?id_type=show'
if 'lastfm://' in notify_params['guid']:
notify_params['lastfm_id'] = '/'.join(notify_params['guid'].split('lastfm://')[1].split('?')[0].split('/')[:2])
@@ -765,7 +765,7 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m
if themoviedb_info.get('imdb_id'):
notify_params['imdb_url'] = 'https://www.imdb.com/title/' + themoviedb_info['imdb_id']
if themoviedb_info.get('themoviedb_id'):
- notify_params['trakt_url'] = 'https://trakt.tv/search/tmdb/{}?type={}'.format(
+ notify_params['trakt_url'] = 'https://trakt.tv/search/tmdb/{}?id_type={}'.format(
notify_params['themoviedb_id'], 'show' if lookup_media_type == 'tv' else 'movie')
# Get TVmaze info (for tv shows only)
@@ -790,7 +790,7 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m
if tvmaze_info.get('thetvdb_id'):
notify_params['thetvdb_url'] = f'https://thetvdb.com/dereferrer/series/{tvmaze_info["thetvdb_id"]}'
- notify_params['trakt_url'] = 'https://trakt.tv/search/tvdb/{}' + str(notify_params['thetvdb_id']) + '?type=show'
+ notify_params['trakt_url'] = 'https://trakt.tv/search/tvdb/{}' + str(notify_params['thetvdb_id']) + '?id_type=show'
if tvmaze_info.get('imdb_id'):
notify_params['imdb_url'] = 'https://www.imdb.com/title/' + tvmaze_info['imdb_id']
notify_params['trakt_url'] = 'https://trakt.tv/search/imdb/' + notify_params['imdb_id']
@@ -824,16 +824,19 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m
poster_thumb = notify_params['thumb']
poster_key = notify_params['rating_key']
poster_title = notify_params['title']
+ plex_slug = notify_params['slug']
elif notify_params['media_type'] in ('season', 'album'):
poster_thumb = notify_params['thumb'] or notify_params['parent_thumb']
poster_key = notify_params['rating_key']
poster_title = '%s - %s' % (notify_params['parent_title'],
notify_params['title'])
+ plex_slug = notify_params['parent_slug']
elif notify_params['media_type'] in ('episode', 'track'):
poster_thumb = notify_params['parent_thumb'] or notify_params['grandparent_thumb']
poster_key = notify_params['parent_rating_key']
poster_title = '%s - %s' % (notify_params['grandparent_title'],
notify_params['parent_title'])
+ plex_slug = notify_params['grandparent_slug']
elif notify_params['media_type'] == 'clip':
if notify_params['extra_type']:
poster_thumb = notify_params['art'].replace('/art', '/thumb') or notify_params['thumb']
@@ -841,10 +844,19 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m
poster_thumb = notify_params['parent_thumb'] or notify_params['thumb']
poster_key = notify_params['rating_key']
poster_title = notify_params['title']
+ plex_slug = notify_params['slug']
else:
poster_thumb = ''
poster_key = ''
poster_title = ''
+ plex_slug = ''
+
+ if notify_params['media_type'] == 'movie':
+ plex_watch_url = f'https://watch.plex.tv/movie/{plex_slug}'
+ elif notify_params['media_type'] in ('show', 'season', 'episode'):
+ plex_watch_url = f'https://watch.plex.tv/show/{plex_slug}'
+ else:
+ plex_watch_url = ''
img_service = helpers.get_img_service(include_self=True)
fallback = 'poster-live' if notify_params['live'] else 'poster'
@@ -943,7 +955,7 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m
now_iso = now.isocalendar()
available_params = {
- # Global paramaters
+ # Global parameters
'tautulli_version': common.RELEASE,
'tautulli_remote': plexpy.CONFIG.GIT_REMOTE,
'tautulli_branch': plexpy.CONFIG.GIT_BRANCH,
@@ -1070,6 +1082,7 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m
'stream_audio_sample_rate': notify_params['stream_audio_sample_rate'],
'stream_audio_language': notify_params['stream_audio_language'],
'stream_audio_language_code': notify_params['stream_audio_language_code'],
+ 'stream_audio_profile': notify_params['stream_audio_profile'],
'stream_subtitle_codec': notify_params['stream_subtitle_codec'],
'stream_subtitle_container': notify_params['stream_subtitle_container'],
'stream_subtitle_format': notify_params['stream_subtitle_format'],
@@ -1154,6 +1167,8 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m
'poster_url': notify_params['poster_url'],
'plex_id': notify_params['plex_id'],
'plex_url': notify_params['plex_url'],
+ 'plex_slug': plex_slug,
+ 'plex_watch_url': plex_watch_url,
'imdb_id': notify_params['imdb_id'],
'imdb_url': notify_params['imdb_url'],
'thetvdb_id': notify_params['thetvdb_id'],
@@ -1201,6 +1216,7 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m
'audio_sample_rate': notify_params['audio_sample_rate'],
'audio_language': notify_params['audio_language'],
'audio_language_code': notify_params['audio_language_code'],
+ 'audio_profile': notify_params['audio_profile'],
'subtitle_codec': notify_params['subtitle_codec'],
'subtitle_container': notify_params['subtitle_container'],
'subtitle_format': notify_params['subtitle_format'],
@@ -1253,7 +1269,7 @@ def build_server_notify_params(notify_action=None, **kwargs):
now_iso = now.isocalendar()
available_params = {
- # Global paramaters
+ # Global parameters
'tautulli_version': common.RELEASE,
'tautulli_remote': plexpy.CONFIG.GIT_REMOTE,
'tautulli_branch': plexpy.CONFIG.GIT_BRANCH,
@@ -1454,8 +1470,11 @@ def strip_tag(data, agent_id=None):
's': [], 'strike': [], 'del': [],
'span': ['class'], 'tg-spoiler': [],
'a': ['href'],
+ 'tg-emoji': ['emoji-id'],
'code': ['class'],
- 'pre': []}
+ 'pre': [],
+ 'blockquote': ['expandable'],
+ }
data = bleach.clean(data, tags=whitelist.keys(), attributes=whitelist, strip=True)
elif agent_id in (10, 14, 20, 25):
diff --git a/plexpy/notifiers.py b/plexpy/notifiers.py
index eb63df33..21002dd2 100644
--- a/plexpy/notifiers.py
+++ b/plexpy/notifiers.py
@@ -2667,7 +2667,8 @@ class NTFY(Notifier):
provider_name = pretty_metadata.get_provider_name(provider)
provider_link = pretty_metadata.get_provider_link(provider)
- actions.append(f"view, View on {provider_name}, {provider_link}, clear=true")
+ if provider_link:
+ actions.append(f"view, View on {provider_name}, {provider_link}, clear=true")
if self.config['incl_pmslink']:
plex_url = pretty_metadata.get_plex_url()
@@ -3390,8 +3391,11 @@ class PUSHOVER(Notifier):
image = pretty_metadata.get_image()
if image:
- files = {'attachment': image}
- headers = {}
+ if len(image[1]) <= 5242880: # 5MB max attachment size
+ files = {'attachment': image}
+ headers = {}
+ else:
+ logger.warn("Tautulli Notifiers :: Image size exceeds 5MB limit for {name}.".format(name=self.NAME))
return self.make_request('https://api.pushover.net/1/messages.json', headers=headers, data=data, files=files)
@@ -4044,7 +4048,7 @@ class TAUTULLIREMOTEAPP(Notifier):
#logger.debug("Salt (base64): {}".format(base64.b64encode(salt)))
payload = {'app_id': mobile_app._ONESIGNAL_APP_ID,
- 'include_player_ids': [device['onesignal_id']],
+ 'include_subscription_ids': [device['onesignal_id']],
'contents': {'en': 'Tautulli Notification'},
'data': {'encrypted': True,
'version': 2,
@@ -4055,11 +4059,11 @@ class TAUTULLIREMOTEAPP(Notifier):
}
else:
logger.warn("Tautulli Notifiers :: Cryptography library is missing. "
- "Tautulli Remote app notifications will be sent unecrypted. "
+ "Tautulli Remote app notifications will be sent unencrypted. "
"Install the library to encrypt the notifications.")
payload = {'app_id': mobile_app._ONESIGNAL_APP_ID,
- 'include_player_ids': [device['onesignal_id']],
+ 'include_subscription_ids': [device['onesignal_id']],
'contents': {'en': 'Tautulli Notification'},
'data': {'encrypted': False,
'plain_text': plaintext_data,
@@ -4070,7 +4074,7 @@ class TAUTULLIREMOTEAPP(Notifier):
headers = {'Content-Type': 'application/json'}
- return self.make_request('https://onesignal.com/api/v1/notifications', headers=headers, json=payload)
+ return self.make_request('https://api.onesignal.com/notifications', headers=headers, json=payload)
def get_devices(self):
db = database.MonitorDatabase()
@@ -4460,7 +4464,8 @@ class WEBHOOK(Notifier):
'select_options': {'GET': 'GET',
'POST': 'POST',
'PUT': 'PUT',
- 'DELETE': 'DELETE'}
+ 'DELETE': 'DELETE',
+ 'PATCH': 'PATCH'}
}
]
diff --git a/plexpy/pmsconnect.py b/plexpy/pmsconnect.py
index fa36219f..ed115897 100644
--- a/plexpy/pmsconnect.py
+++ b/plexpy/pmsconnect.py
@@ -823,6 +823,9 @@ class PmsConnect(object):
'original_title': helpers.get_xml_attr(metadata_main, 'originalTitle'),
'sort_title': helpers.get_xml_attr(metadata_main, 'titleSort'),
'edition_title': helpers.get_xml_attr(metadata_main, 'editionTitle'),
+ 'slug': helpers.get_xml_attr(metadata_main, 'slug'),
+ 'parent_slug': helpers.get_xml_attr(metadata_main, 'parentSlug'),
+ 'grandparent_slug': helpers.get_xml_attr(metadata_main, 'grandparentSlug'),
'media_index': helpers.get_xml_attr(metadata_main, 'index'),
'parent_media_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
'studio': helpers.get_xml_attr(metadata_main, 'studio'),
@@ -883,6 +886,9 @@ class PmsConnect(object):
'original_title': helpers.get_xml_attr(metadata_main, 'originalTitle'),
'sort_title': helpers.get_xml_attr(metadata_main, 'titleSort'),
'edition_title': helpers.get_xml_attr(metadata_main, 'editionTitle'),
+ 'slug': helpers.get_xml_attr(metadata_main, 'slug'),
+ 'parent_slug': helpers.get_xml_attr(metadata_main, 'parentSlug'),
+ 'grandparent_slug': helpers.get_xml_attr(metadata_main, 'grandparentSlug'),
'media_index': helpers.get_xml_attr(metadata_main, 'index'),
'parent_media_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
'studio': helpers.get_xml_attr(metadata_main, 'studio'),
@@ -949,6 +955,9 @@ class PmsConnect(object):
'original_title': helpers.get_xml_attr(metadata_main, 'originalTitle'),
'sort_title': helpers.get_xml_attr(metadata_main, 'titleSort'),
'edition_title': helpers.get_xml_attr(metadata_main, 'editionTitle'),
+ 'slug': helpers.get_xml_attr(metadata_main, 'slug'),
+ 'parent_slug': helpers.get_xml_attr(metadata_main, 'parentSlug'),
+ 'grandparent_slug': helpers.get_xml_attr(metadata_main, 'grandparentSlug'),
'media_index': helpers.get_xml_attr(metadata_main, 'index'),
'parent_media_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
'studio': show_details.get('studio', ''),
@@ -1032,6 +1041,9 @@ class PmsConnect(object):
'original_title': helpers.get_xml_attr(metadata_main, 'originalTitle'),
'sort_title': helpers.get_xml_attr(metadata_main, 'titleSort'),
'edition_title': helpers.get_xml_attr(metadata_main, 'editionTitle'),
+ 'slug': helpers.get_xml_attr(metadata_main, 'slug'),
+ 'parent_slug': helpers.get_xml_attr(metadata_main, 'parentSlug'),
+ 'grandparent_slug': helpers.get_xml_attr(metadata_main, 'grandparentSlug'),
'media_index': helpers.get_xml_attr(metadata_main, 'index'),
'parent_media_index': parent_media_index,
'studio': show_details.get('studio', ''),
@@ -1088,6 +1100,9 @@ class PmsConnect(object):
'original_title': helpers.get_xml_attr(metadata_main, 'originalTitle'),
'sort_title': helpers.get_xml_attr(metadata_main, 'titleSort'),
'edition_title': helpers.get_xml_attr(metadata_main, 'editionTitle'),
+ 'slug': helpers.get_xml_attr(metadata_main, 'slug'),
+ 'parent_slug': helpers.get_xml_attr(metadata_main, 'parentSlug'),
+ 'grandparent_slug': helpers.get_xml_attr(metadata_main, 'grandparentSlug'),
'media_index': helpers.get_xml_attr(metadata_main, 'index'),
'parent_media_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
'studio': helpers.get_xml_attr(metadata_main, 'studio'),
@@ -1145,6 +1160,9 @@ class PmsConnect(object):
'original_title': helpers.get_xml_attr(metadata_main, 'originalTitle'),
'sort_title': helpers.get_xml_attr(metadata_main, 'titleSort'),
'edition_title': helpers.get_xml_attr(metadata_main, 'editionTitle'),
+ 'slug': helpers.get_xml_attr(metadata_main, 'slug'),
+ 'parent_slug': helpers.get_xml_attr(metadata_main, 'parentSlug'),
+ 'grandparent_slug': helpers.get_xml_attr(metadata_main, 'grandparentSlug'),
'media_index': helpers.get_xml_attr(metadata_main, 'index'),
'parent_media_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
'studio': helpers.get_xml_attr(metadata_main, 'studio'),
@@ -1205,6 +1223,9 @@ class PmsConnect(object):
'original_title': helpers.get_xml_attr(metadata_main, 'originalTitle'),
'sort_title': helpers.get_xml_attr(metadata_main, 'titleSort'),
'edition_title': helpers.get_xml_attr(metadata_main, 'editionTitle'),
+ 'slug': helpers.get_xml_attr(metadata_main, 'slug'),
+ 'parent_slug': helpers.get_xml_attr(metadata_main, 'parentSlug'),
+ 'grandparent_slug': helpers.get_xml_attr(metadata_main, 'grandparentSlug'),
'media_index': helpers.get_xml_attr(metadata_main, 'index'),
'parent_media_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
'studio': helpers.get_xml_attr(metadata_main, 'studio'),
@@ -1261,6 +1282,9 @@ class PmsConnect(object):
'original_title': helpers.get_xml_attr(metadata_main, 'originalTitle'),
'sort_title': helpers.get_xml_attr(metadata_main, 'titleSort'),
'edition_title': helpers.get_xml_attr(metadata_main, 'editionTitle'),
+ 'slug': helpers.get_xml_attr(metadata_main, 'slug'),
+ 'parent_slug': helpers.get_xml_attr(metadata_main, 'parentSlug'),
+ 'grandparent_slug': helpers.get_xml_attr(metadata_main, 'grandparentSlug'),
'media_index': helpers.get_xml_attr(metadata_main, 'index'),
'parent_media_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
'studio': helpers.get_xml_attr(metadata_main, 'studio'),
@@ -1318,6 +1342,9 @@ class PmsConnect(object):
'original_title': helpers.get_xml_attr(metadata_main, 'originalTitle'),
'sort_title': helpers.get_xml_attr(metadata_main, 'titleSort'),
'edition_title': helpers.get_xml_attr(metadata_main, 'editionTitle'),
+ 'slug': helpers.get_xml_attr(metadata_main, 'slug'),
+ 'parent_slug': helpers.get_xml_attr(metadata_main, 'parentSlug'),
+ 'grandparent_slug': helpers.get_xml_attr(metadata_main, 'grandparentSlug'),
'media_index': helpers.get_xml_attr(metadata_main, 'index'),
'parent_media_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
'studio': helpers.get_xml_attr(metadata_main, 'studio'),
@@ -1375,6 +1402,9 @@ class PmsConnect(object):
'original_title': helpers.get_xml_attr(metadata_main, 'originalTitle'),
'sort_title': helpers.get_xml_attr(metadata_main, 'titleSort'),
'edition_title': helpers.get_xml_attr(metadata_main, 'editionTitle'),
+ 'slug': helpers.get_xml_attr(metadata_main, 'slug'),
+ 'parent_slug': helpers.get_xml_attr(metadata_main, 'parentSlug'),
+ 'grandparent_slug': helpers.get_xml_attr(metadata_main, 'grandparentSlug'),
'media_index': helpers.get_xml_attr(metadata_main, 'index'),
'parent_media_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
'studio': helpers.get_xml_attr(metadata_main, 'studio'),
@@ -1454,6 +1484,9 @@ class PmsConnect(object):
'original_title': helpers.get_xml_attr(metadata_main, 'originalTitle'),
'sort_title': helpers.get_xml_attr(metadata_main, 'titleSort'),
'edition_title': helpers.get_xml_attr(metadata_main, 'editionTitle'),
+ 'slug': helpers.get_xml_attr(metadata_main, 'slug'),
+ 'parent_slug': helpers.get_xml_attr(metadata_main, 'parentSlug'),
+ 'grandparent_slug': helpers.get_xml_attr(metadata_main, 'grandparentSlug'),
'media_index': helpers.get_xml_attr(metadata_main, 'index'),
'parent_media_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
'studio': helpers.get_xml_attr(metadata_main, 'studio'),
@@ -2063,6 +2096,7 @@ class PmsConnect(object):
'stream_audio_channel_layout_': stream_audio_channel_layouts_,
'stream_audio_language': helpers.get_xml_attr(audio_stream_info, 'language'),
'stream_audio_language_code': helpers.get_xml_attr(audio_stream_info, 'languageCode'),
+ 'stream_audio_profile': helpers.get_xml_attr(audio_stream_info, 'profile'),
'stream_audio_decision': helpers.get_xml_attr(audio_stream_info, 'decision') or 'direct play'
}
else:
@@ -2075,6 +2109,7 @@ class PmsConnect(object):
'stream_audio_channel_layout_': '',
'stream_audio_language': '',
'stream_audio_language_code': '',
+ 'stream_audio_profile': '',
'stream_audio_decision': ''
}
@@ -3148,6 +3183,7 @@ class PmsConnect(object):
if media_type == 'season' or media_type == 'album':
try:
metadata = self.get_metadata_details(rating_key=rating_key)
+ title = metadata['parent_title']
rating_key = metadata['parent_rating_key']
section_id = metadata['section_id']
library_name = metadata['library_name']
@@ -3158,6 +3194,7 @@ class PmsConnect(object):
elif media_type == 'episode' or media_type == 'track':
try:
metadata = self.get_metadata_details(rating_key=rating_key)
+ title = metadata['grandparent_title']
rating_key = metadata['grandparent_rating_key']
section_id = metadata['section_id']
library_name = metadata['library_name']
@@ -3165,9 +3202,10 @@ class PmsConnect(object):
logger.warn("Tautulli Pmsconnect :: Unable to get grandparent_rating_key for get_rating_keys_list: %s." % e)
return {}
- elif media_type == 'artist':
+ elif media_type == 'show' or media_type == 'artist':
try:
metadata = self.get_metadata_details(rating_key=rating_key)
+ title = metadata['title']
section_id = metadata['section_id']
library_name = metadata['library_name']
except Exception as e:
@@ -3197,8 +3235,6 @@ class PmsConnect(object):
if a.getAttribute('size') == '0':
return {}
- title = helpers.get_xml_attr(a, 'title2')
-
if a.getElementsByTagName('Directory'):
parents_metadata = a.getElementsByTagName('Directory')
else:
@@ -3352,10 +3388,10 @@ class PmsConnect(object):
def get_dynamic_range(stream):
extended_display_title = helpers.get_xml_attr(stream, 'extendedDisplayTitle')
bit_depth = helpers.cast_to_int(helpers.get_xml_attr(stream, 'bitDepth'))
- color_space = helpers.get_xml_attr(stream, 'colorSpace')
+ color_trc = helpers.get_xml_attr(stream, 'colorTrc')
DOVI_profile = helpers.get_xml_attr(stream, 'DOVIProfile')
- HDR = bool(bit_depth > 8 and 'bt2020' in color_space)
+ HDR = bool(bit_depth > 8 and (color_trc == 'smpte2084' or color_trc == 'arib-std-b67'))
DV = bool(DOVI_profile)
if not HDR and not DV:
diff --git a/plexpy/version.py b/plexpy/version.py
index 08fcf9e3..a2a92f99 100644
--- a/plexpy/version.py
+++ b/plexpy/version.py
@@ -16,4 +16,4 @@
# along with Tautulli. If not, see .
PLEXPY_BRANCH = "master"
-PLEXPY_RELEASE_VERSION = "v2.14.6"
\ No newline at end of file
+PLEXPY_RELEASE_VERSION = "v2.15.2"
\ No newline at end of file
diff --git a/plexpy/webauth.py b/plexpy/webauth.py
index 05c81a81..67658d15 100644
--- a/plexpy/webauth.py
+++ b/plexpy/webauth.py
@@ -50,7 +50,7 @@ def plex_user_login(token=None, headers=None):
user_token = None
user_id = None
- # Try to login to Plex.tv to check if the user has a vaild account
+ # Try to login to Plex.tv to check if the user has a valid account
if token:
plex_tv = PlexTV(token=token, headers=headers)
plex_user = plex_tv.get_plex_account_details()
@@ -176,7 +176,10 @@ def check_auth(*args, **kwargs):
raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT)
else:
- redirect_uri = cherrypy.request.wsgi_environ['REQUEST_URI']
+ if cherrypy.request.headers.get('X-Requested-With') == 'XMLHttpRequest':
+ raise cherrypy.HTTPError(401)
+
+ redirect_uri = cherrypy.request.path_info
if redirect_uri:
redirect_uri = '?redirect_uri=' + quote(redirect_uri)
diff --git a/plexpy/webserve.py b/plexpy/webserve.py
index 150bc18d..3f8890cc 100644
--- a/plexpy/webserve.py
+++ b/plexpy/webserve.py
@@ -608,7 +608,7 @@ class WebInterface(object):
status_message = ''
else:
result = None
- status_message = 'An error occured.'
+ status_message = 'An error occurred.'
return serve_template(template_name="edit_library.html", title="Edit Library",
data=result, server_id=plexpy.CONFIG.PMS_IDENTIFIER, status_message=status_message)
@@ -1347,7 +1347,7 @@ class WebInterface(object):
status_message = ''
else:
result = None
- status_message = 'An error occured.'
+ status_message = 'An error occurred.'
return serve_template(template_name="edit_user.html", title="Edit User", data=result, status_message=status_message)
@@ -1365,7 +1365,7 @@ class WebInterface(object):
keep_history (int): 0 or 1
allow_guest (int): 0 or 1
- Optional paramters:
+ Optional parameters:
None
Returns:
@@ -3031,7 +3031,7 @@ class WebInterface(object):
""" Delete the Tautulli notification logs.
```
- Required paramters:
+ Required parameters:
None
Optional parameters:
@@ -3056,7 +3056,7 @@ class WebInterface(object):
""" Delete the Tautulli newsletter logs.
```
- Required paramters:
+ Required parameters:
None
Optional parameters:
@@ -3081,7 +3081,7 @@ class WebInterface(object):
""" Delete the Tautulli login logs.
```
- Required paramters:
+ Required parameters:
None
Optional parameters:
@@ -5352,6 +5352,7 @@ class WebInterface(object):
"tvdb://121361"
],
"grandparent_rating_key": "1219",
+ "grandparent_slug": "game-of-thrones",
"grandparent_thumb": "/library/metadata/1219/thumb/1462175063",
"grandparent_title": "Game of Thrones",
"grandparent_year": "2011",
@@ -5484,6 +5485,7 @@ class WebInterface(object):
],
"parent_media_index": "6",
"parent_rating_key": "153036",
+ "parent_slug": "game-of-thrones",
"parent_thumb": "/library/metadata/153036/thumb/1462175062",
"parent_title": "Season 6",
"parent_year": "2016",
@@ -5491,6 +5493,7 @@ class WebInterface(object):
"rating_image": "",
"rating_key": "153037",
"section_id": "2",
+ "slug": "game-of-thrones",
"sort_title": "Red Woman",
"studio": "Revolution Sun Studios",
"summary": "The fate of Jon Snow is revealed. Daenerys meets a strong man. Cersei sees her daughter once again.",
@@ -5918,6 +5921,7 @@ class WebInterface(object):
"stream_audio_decision": "direct play",
"stream_audio_language": "",
"stream_audio_language_code": "",
+ "stream_audio_profile": "",
"stream_audio_sample_rate": "48000",
"stream_bitrate": "10617",
"stream_container": "mkv",
@@ -6963,6 +6967,7 @@ class WebInterface(object):
"file_size": 57793562,
"filename": null,
"individual_files": 1,
+ "logo_level": 0,
"media_info_level": 1,
"media_type": "collection",
"media_type_title": "Collection",
@@ -7058,7 +7063,7 @@ class WebInterface(object):
@addtoapi()
def export_metadata(self, section_id=None, user_id=None, rating_key=None, file_format='csv',
metadata_level=1, media_info_level=1,
- thumb_level=0, art_level=0,
+ thumb_level=0, art_level=0, logo_level=0,
custom_fields='', export_type='all', individual_files=False, **kwargs):
""" Export library or media metadata to a file
@@ -7074,6 +7079,7 @@ class WebInterface(object):
media_info_level (int): The level of media info to export (default 1)
thumb_level (int): The level of poster/cover images to export (default 0)
art_level (int): The level of background artwork images to export (default 0)
+ logo_level (int): The level of logo images to export (default 0)
custom_fields (str): Comma separated list of custom fields to export
in addition to the export level selected
export_type (str): 'collection' or 'playlist' for library/user export,
@@ -7094,6 +7100,7 @@ class WebInterface(object):
media_info_level=media_info_level,
thumb_level=thumb_level,
art_level=art_level,
+ logo_level=logo_level,
custom_fields=custom_fields,
export_type=export_type,
individual_files=individual_files).export()
@@ -7183,7 +7190,7 @@ class WebInterface(object):
result = exporter.get_export(export_id=export_id)
if result and result['complete'] == 1 and result['exists']:
- if result['thumb_level'] or result['art_level'] or result['individual_files']:
+ if result['thumb_level'] or result['art_level'] or result['logo_level'] or result['individual_files']:
directory = exporter.format_export_directory(result['title'], result['timestamp'])
dirpath = exporter.get_export_dirpath(directory)
zip_filename = '{}.zip'.format(directory)
diff --git a/plexpy/webstart.py b/plexpy/webstart.py
index 8a6edc6e..323c7e8e 100644
--- a/plexpy/webstart.py
+++ b/plexpy/webstart.py
@@ -21,6 +21,7 @@ import sys
import cheroot.errors
import cherrypy
+import cherrypy_cors
import plexpy
from plexpy import logger
@@ -62,6 +63,7 @@ def restart():
def initialize(options):
+ cherrypy_cors.install()
# HTTPS stuff stolen from sickbeard
enable_https = options['enable_https']
@@ -91,7 +93,8 @@ def initialize(options):
'server.socket_timeout': 60,
'tools.encode.on': True,
'tools.encode.encoding': 'utf-8',
- 'tools.decode.on': True
+ 'tools.decode.on': True,
+ 'cors.expose.on': True,
}
if plexpy.DEV:
@@ -171,6 +174,12 @@ def initialize(options):
'/status': {
'tools.auth_basic.on': False
},
+ '/newsletter': {
+ 'tools.auth_basic.on': False
+ },
+ '/image': {
+ 'tools.auth_basic.on': False
+ },
'/interfaces': {
'tools.staticdir.on': True,
'tools.staticdir.dir': "interfaces",
diff --git a/requirements.txt b/requirements.txt
index d37487f1..120b01ac 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,53 +1,53 @@
apscheduler==3.10.1
arrow==1.3.0
-backports.zoneinfo==0.2.1;python_version<"3.9"
beautifulsoup4==4.12.3
-bleach==6.1.0
-certifi==2024.7.4
+bleach==6.2.0
+certifi==2024.8.30
cheroot==10.0.1
cherrypy==18.10.0
+cherrypy-cors==1.7.0
cloudinary==1.41.0
distro==1.9.0
-dnspython==2.6.1
+dnspython==2.7.0
facebook-sdk==3.1.0
future==1.0.0
ga4mp==2.0.4
gntp==1.0.3
html5lib==1.1
httpagentparser==1.9.5
-idna==3.7
-importlib-metadata==8.2.0
-importlib-resources==6.4.0
+idna==3.10
+importlib-metadata==8.5.0
+importlib-resources==6.4.5
git+https://github.com/Tautulli/ipwhois.git@master#egg=ipwhois
IPy==1.01
-Mako==1.3.5
-MarkupSafe==2.1.5
+Mako==1.3.6
+MarkupSafe==3.0.2
musicbrainzngs==0.7.1
-packaging==24.1
+packaging==24.2
paho-mqtt==2.1.0
-platformdirs==4.2.2
-plexapi==4.15.16
+platformdirs==4.3.6
+plexapi==4.16.1
portend==3.2.0
-profilehooks==1.12.0
-PyJWT==2.9.0
-pyparsing==3.1.2
+profilehooks==1.13.0
+PyJWT==2.10.1
+pyparsing==3.2.0
python-dateutil==2.9.0.post0
python-twitter==3.5
-pytz==2024.1
+pytz==2024.2
requests==2.32.3
requests-oauthlib==2.0.0
rumps==0.4.0; platform_system == "Darwin"
-simplejson==3.19.2
+simplejson==3.19.3
six==1.16.0
tempora==5.7.0
-tokenize-rt==6.0.0
-tzdata==2024.1
+tokenize-rt==6.1.0
+tzdata==2024.2
tzlocal==5.0.1
urllib3<2
webencodings==0.5.1
websocket-client==1.8.0
-xmltodict==0.13.0
-zipp==3.19.2
+xmltodict==0.14.2
+zipp==3.21.0
# configobj==5.1.0
# sgmllib3k==1.0.0
diff --git a/start.sh b/start.sh
index a9970df7..8896ac87 100755
--- a/start.sh
+++ b/start.sh
@@ -12,7 +12,7 @@ if [[ "$TAUTULLI_DOCKER" == "True" ]]; then
echo "Running Tautulli using user tautulli (uid=$(id -u tautulli)) and group tautulli (gid=$(id -g tautulli))"
exec gosu tautulli "$@"
else
- python_versions=("python3.11" "python3.10" "python3.9" "python3.8" "python3" "python")
+ python_versions=("python3.11" "python3.10" "python3.9" "python3" "python")
for cmd in "${python_versions[@]}"; do
if command -v "$cmd" >/dev/null; then
echo "Starting Tautulli with $cmd."