Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .venv/lib/python3.12/site-packages/PIL/AvifImagePlugin.py +293 -0
- .venv/lib/python3.12/site-packages/PIL/FliImagePlugin.py +184 -0
- .venv/lib/python3.12/site-packages/PIL/FpxImagePlugin.py +258 -0
- .venv/lib/python3.12/site-packages/PIL/ImageChops.py +311 -0
- .venv/lib/python3.12/site-packages/PIL/ImageSequence.py +88 -0
- .venv/lib/python3.12/site-packages/PIL/ImageText.py +508 -0
- .venv/lib/python3.12/site-packages/PIL/ImageTransform.py +136 -0
- .venv/lib/python3.12/site-packages/PIL/ImtImagePlugin.py +103 -0
- .venv/lib/python3.12/site-packages/PIL/PsdImagePlugin.py +337 -0
- .venv/lib/python3.12/site-packages/PIL/QoiImagePlugin.py +235 -0
- .venv/lib/python3.12/site-packages/PIL/WmfImagePlugin.py +183 -0
- .venv/lib/python3.12/site-packages/PIL/XVThumbImagePlugin.py +83 -0
- .venv/lib/python3.12/site-packages/PIL/_imagingft.pyi +70 -0
- .venv/lib/python3.12/site-packages/PIL/_webp.pyi +3 -0
- .venv/lib/python3.12/site-packages/audioread/__init__.py +131 -0
- .venv/lib/python3.12/site-packages/audioread/base.py +18 -0
- .venv/lib/python3.12/site-packages/audioread/exceptions.py +25 -0
- .venv/lib/python3.12/site-packages/audioread/ffdec.py +320 -0
- .venv/lib/python3.12/site-packages/audioread/gstdec.py +429 -0
- .venv/lib/python3.12/site-packages/audioread/macca.py +348 -0
- .venv/lib/python3.12/site-packages/audioread/maddec.py +86 -0
- .venv/lib/python3.12/site-packages/audioread/rawread.py +149 -0
- .venv/lib/python3.12/site-packages/babel-2.18.0.dist-info/INSTALLER +1 -0
- .venv/lib/python3.12/site-packages/babel-2.18.0.dist-info/METADATA +58 -0
- .venv/lib/python3.12/site-packages/babel-2.18.0.dist-info/RECORD +1122 -0
- .venv/lib/python3.12/site-packages/babel-2.18.0.dist-info/REQUESTED +0 -0
- .venv/lib/python3.12/site-packages/babel-2.18.0.dist-info/WHEEL +5 -0
- .venv/lib/python3.12/site-packages/babel-2.18.0.dist-info/entry_points.txt +20 -0
- .venv/lib/python3.12/site-packages/babel-2.18.0.dist-info/top_level.txt +1 -0
- .venv/lib/python3.12/site-packages/bluecodec-0.1.0.dist-info/INSTALLER +1 -0
- .venv/lib/python3.12/site-packages/bluecodec-0.1.0.dist-info/METADATA +47 -0
- .venv/lib/python3.12/site-packages/bluecodec-0.1.0.dist-info/RECORD +17 -0
- .venv/lib/python3.12/site-packages/bluecodec-0.1.0.dist-info/REQUESTED +0 -0
- .venv/lib/python3.12/site-packages/bluecodec-0.1.0.dist-info/WHEEL +4 -0
- .venv/lib/python3.12/site-packages/bluecodec-0.1.0.dist-info/direct_url.json +1 -0
- .venv/lib/python3.12/site-packages/bluecodec-0.1.0.dist-info/uv_build.json +1 -0
- .venv/lib/python3.12/site-packages/certifi-2026.2.25.dist-info/INSTALLER +1 -0
- .venv/lib/python3.12/site-packages/certifi-2026.2.25.dist-info/METADATA +78 -0
- .venv/lib/python3.12/site-packages/certifi-2026.2.25.dist-info/RECORD +12 -0
- .venv/lib/python3.12/site-packages/certifi-2026.2.25.dist-info/REQUESTED +0 -0
- .venv/lib/python3.12/site-packages/certifi-2026.2.25.dist-info/WHEEL +5 -0
- .venv/lib/python3.12/site-packages/certifi-2026.2.25.dist-info/top_level.txt +1 -0
- .venv/lib/python3.12/site-packages/cffi/__init__.py +14 -0
- .venv/lib/python3.12/site-packages/cffi/_cffi_errors.h +149 -0
- .venv/lib/python3.12/site-packages/cffi/_cffi_include.h +389 -0
- .venv/lib/python3.12/site-packages/cffi/_embedding.h +550 -0
- .venv/lib/python3.12/site-packages/cffi/_imp_emulation.py +83 -0
- .venv/lib/python3.12/site-packages/cffi/_shimmed_dist_utils.py +45 -0
- .venv/lib/python3.12/site-packages/cffi/api.py +967 -0
- .venv/lib/python3.12/site-packages/cffi/backend_ctypes.py +1121 -0
.venv/lib/python3.12/site-packages/PIL/AvifImagePlugin.py
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
from io import BytesIO
|
| 5 |
+
from typing import IO
|
| 6 |
+
|
| 7 |
+
from . import ExifTags, Image, ImageFile
|
| 8 |
+
|
| 9 |
+
try:
|
| 10 |
+
from . import _avif
|
| 11 |
+
|
| 12 |
+
SUPPORTED = True
|
| 13 |
+
except ImportError:
|
| 14 |
+
SUPPORTED = False
|
| 15 |
+
|
| 16 |
+
# Decoder options as module globals, until there is a way to pass parameters
|
| 17 |
+
# to Image.open (see https://github.com/python-pillow/Pillow/issues/569)
|
| 18 |
+
DECODE_CODEC_CHOICE = "auto"
|
| 19 |
+
DEFAULT_MAX_THREADS = 0
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
def get_codec_version(codec_name: str) -> str | None:
|
| 23 |
+
versions = _avif.codec_versions()
|
| 24 |
+
for version in versions.split(", "):
|
| 25 |
+
if version.split(" [")[0] == codec_name:
|
| 26 |
+
return version.split(":")[-1].split(" ")[0]
|
| 27 |
+
return None
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def _accept(prefix: bytes) -> bool | str:
|
| 31 |
+
if prefix[4:8] != b"ftyp":
|
| 32 |
+
return False
|
| 33 |
+
major_brand = prefix[8:12]
|
| 34 |
+
if major_brand in (
|
| 35 |
+
# coding brands
|
| 36 |
+
b"avif",
|
| 37 |
+
b"avis",
|
| 38 |
+
# We accept files with AVIF container brands; we can't yet know if
|
| 39 |
+
# the ftyp box has the correct compatible brands, but if it doesn't
|
| 40 |
+
# then the plugin will raise a SyntaxError which Pillow will catch
|
| 41 |
+
# before moving on to the next plugin that accepts the file.
|
| 42 |
+
#
|
| 43 |
+
# Also, because this file might not actually be an AVIF file, we
|
| 44 |
+
# don't raise an error if AVIF support isn't properly compiled.
|
| 45 |
+
b"mif1",
|
| 46 |
+
b"msf1",
|
| 47 |
+
):
|
| 48 |
+
if not SUPPORTED:
|
| 49 |
+
return (
|
| 50 |
+
"image file could not be identified because AVIF support not installed"
|
| 51 |
+
)
|
| 52 |
+
return True
|
| 53 |
+
return False
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def _get_default_max_threads() -> int:
|
| 57 |
+
if DEFAULT_MAX_THREADS:
|
| 58 |
+
return DEFAULT_MAX_THREADS
|
| 59 |
+
if hasattr(os, "sched_getaffinity"):
|
| 60 |
+
return len(os.sched_getaffinity(0))
|
| 61 |
+
else:
|
| 62 |
+
return os.cpu_count() or 1
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
class AvifImageFile(ImageFile.ImageFile):
|
| 66 |
+
format = "AVIF"
|
| 67 |
+
format_description = "AVIF image"
|
| 68 |
+
__frame = -1
|
| 69 |
+
|
| 70 |
+
def _open(self) -> None:
|
| 71 |
+
if not SUPPORTED:
|
| 72 |
+
msg = "image file could not be opened because AVIF support not installed"
|
| 73 |
+
raise SyntaxError(msg)
|
| 74 |
+
|
| 75 |
+
if DECODE_CODEC_CHOICE != "auto" and not _avif.decoder_codec_available(
|
| 76 |
+
DECODE_CODEC_CHOICE
|
| 77 |
+
):
|
| 78 |
+
msg = "Invalid opening codec"
|
| 79 |
+
raise ValueError(msg)
|
| 80 |
+
|
| 81 |
+
assert self.fp is not None
|
| 82 |
+
self._decoder = _avif.AvifDecoder(
|
| 83 |
+
self.fp.read(),
|
| 84 |
+
DECODE_CODEC_CHOICE,
|
| 85 |
+
_get_default_max_threads(),
|
| 86 |
+
)
|
| 87 |
+
|
| 88 |
+
# Get info from decoder
|
| 89 |
+
self._size, self.n_frames, self._mode, icc, exif, exif_orientation, xmp = (
|
| 90 |
+
self._decoder.get_info()
|
| 91 |
+
)
|
| 92 |
+
self.is_animated = self.n_frames > 1
|
| 93 |
+
|
| 94 |
+
if icc:
|
| 95 |
+
self.info["icc_profile"] = icc
|
| 96 |
+
if xmp:
|
| 97 |
+
self.info["xmp"] = xmp
|
| 98 |
+
|
| 99 |
+
if exif_orientation != 1 or exif:
|
| 100 |
+
exif_data = Image.Exif()
|
| 101 |
+
if exif:
|
| 102 |
+
exif_data.load(exif)
|
| 103 |
+
original_orientation = exif_data.get(ExifTags.Base.Orientation, 1)
|
| 104 |
+
else:
|
| 105 |
+
original_orientation = 1
|
| 106 |
+
if exif_orientation != original_orientation:
|
| 107 |
+
exif_data[ExifTags.Base.Orientation] = exif_orientation
|
| 108 |
+
exif = exif_data.tobytes()
|
| 109 |
+
if exif:
|
| 110 |
+
self.info["exif"] = exif
|
| 111 |
+
self.seek(0)
|
| 112 |
+
|
| 113 |
+
def seek(self, frame: int) -> None:
|
| 114 |
+
if not self._seek_check(frame):
|
| 115 |
+
return
|
| 116 |
+
|
| 117 |
+
# Set tile
|
| 118 |
+
self.__frame = frame
|
| 119 |
+
self.tile = [ImageFile._Tile("raw", (0, 0) + self.size, 0, self.mode)]
|
| 120 |
+
|
| 121 |
+
def load(self) -> Image.core.PixelAccess | None:
|
| 122 |
+
if self.tile:
|
| 123 |
+
# We need to load the image data for this frame
|
| 124 |
+
data, timescale, pts_in_timescales, duration_in_timescales = (
|
| 125 |
+
self._decoder.get_frame(self.__frame)
|
| 126 |
+
)
|
| 127 |
+
self.info["timestamp"] = round(1000 * (pts_in_timescales / timescale))
|
| 128 |
+
self.info["duration"] = round(1000 * (duration_in_timescales / timescale))
|
| 129 |
+
|
| 130 |
+
if self.fp and self._exclusive_fp:
|
| 131 |
+
self.fp.close()
|
| 132 |
+
self.fp = BytesIO(data)
|
| 133 |
+
|
| 134 |
+
return super().load()
|
| 135 |
+
|
| 136 |
+
def load_seek(self, pos: int) -> None:
|
| 137 |
+
pass
|
| 138 |
+
|
| 139 |
+
def tell(self) -> int:
|
| 140 |
+
return self.__frame
|
| 141 |
+
|
| 142 |
+
|
| 143 |
+
def _save_all(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
|
| 144 |
+
_save(im, fp, filename, save_all=True)
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
def _save(
|
| 148 |
+
im: Image.Image, fp: IO[bytes], filename: str | bytes, save_all: bool = False
|
| 149 |
+
) -> None:
|
| 150 |
+
info = im.encoderinfo.copy()
|
| 151 |
+
if save_all:
|
| 152 |
+
append_images = list(info.get("append_images", []))
|
| 153 |
+
else:
|
| 154 |
+
append_images = []
|
| 155 |
+
|
| 156 |
+
total = 0
|
| 157 |
+
for ims in [im] + append_images:
|
| 158 |
+
total += getattr(ims, "n_frames", 1)
|
| 159 |
+
|
| 160 |
+
quality = info.get("quality", 75)
|
| 161 |
+
if not isinstance(quality, int) or quality < 0 or quality > 100:
|
| 162 |
+
msg = "Invalid quality setting"
|
| 163 |
+
raise ValueError(msg)
|
| 164 |
+
|
| 165 |
+
duration = info.get("duration", 0)
|
| 166 |
+
subsampling = info.get("subsampling", "4:2:0")
|
| 167 |
+
speed = info.get("speed", 6)
|
| 168 |
+
max_threads = info.get("max_threads", _get_default_max_threads())
|
| 169 |
+
codec = info.get("codec", "auto")
|
| 170 |
+
if codec != "auto" and not _avif.encoder_codec_available(codec):
|
| 171 |
+
msg = "Invalid saving codec"
|
| 172 |
+
raise ValueError(msg)
|
| 173 |
+
range_ = info.get("range", "full")
|
| 174 |
+
tile_rows_log2 = info.get("tile_rows", 0)
|
| 175 |
+
tile_cols_log2 = info.get("tile_cols", 0)
|
| 176 |
+
alpha_premultiplied = bool(info.get("alpha_premultiplied", False))
|
| 177 |
+
autotiling = bool(info.get("autotiling", tile_rows_log2 == tile_cols_log2 == 0))
|
| 178 |
+
|
| 179 |
+
icc_profile = info.get("icc_profile", im.info.get("icc_profile"))
|
| 180 |
+
exif_orientation = 1
|
| 181 |
+
if exif := info.get("exif"):
|
| 182 |
+
if isinstance(exif, Image.Exif):
|
| 183 |
+
exif_data = exif
|
| 184 |
+
else:
|
| 185 |
+
exif_data = Image.Exif()
|
| 186 |
+
exif_data.load(exif)
|
| 187 |
+
if ExifTags.Base.Orientation in exif_data:
|
| 188 |
+
exif_orientation = exif_data.pop(ExifTags.Base.Orientation)
|
| 189 |
+
exif = exif_data.tobytes() if exif_data else b""
|
| 190 |
+
elif isinstance(exif, Image.Exif):
|
| 191 |
+
exif = exif_data.tobytes()
|
| 192 |
+
|
| 193 |
+
xmp = info.get("xmp")
|
| 194 |
+
|
| 195 |
+
if isinstance(xmp, str):
|
| 196 |
+
xmp = xmp.encode("utf-8")
|
| 197 |
+
|
| 198 |
+
advanced = info.get("advanced")
|
| 199 |
+
if advanced is not None:
|
| 200 |
+
if isinstance(advanced, dict):
|
| 201 |
+
advanced = advanced.items()
|
| 202 |
+
try:
|
| 203 |
+
advanced = tuple(advanced)
|
| 204 |
+
except TypeError:
|
| 205 |
+
invalid = True
|
| 206 |
+
else:
|
| 207 |
+
invalid = any(not isinstance(v, tuple) or len(v) != 2 for v in advanced)
|
| 208 |
+
if invalid:
|
| 209 |
+
msg = (
|
| 210 |
+
"advanced codec options must be a dict of key-value string "
|
| 211 |
+
"pairs or a series of key-value two-tuples"
|
| 212 |
+
)
|
| 213 |
+
raise ValueError(msg)
|
| 214 |
+
|
| 215 |
+
# Setup the AVIF encoder
|
| 216 |
+
enc = _avif.AvifEncoder(
|
| 217 |
+
im.size,
|
| 218 |
+
subsampling,
|
| 219 |
+
quality,
|
| 220 |
+
speed,
|
| 221 |
+
max_threads,
|
| 222 |
+
codec,
|
| 223 |
+
range_,
|
| 224 |
+
tile_rows_log2,
|
| 225 |
+
tile_cols_log2,
|
| 226 |
+
alpha_premultiplied,
|
| 227 |
+
autotiling,
|
| 228 |
+
icc_profile or b"",
|
| 229 |
+
exif or b"",
|
| 230 |
+
exif_orientation,
|
| 231 |
+
xmp or b"",
|
| 232 |
+
advanced,
|
| 233 |
+
)
|
| 234 |
+
|
| 235 |
+
# Add each frame
|
| 236 |
+
frame_idx = 0
|
| 237 |
+
frame_duration = 0
|
| 238 |
+
cur_idx = im.tell()
|
| 239 |
+
is_single_frame = total == 1
|
| 240 |
+
try:
|
| 241 |
+
for ims in [im] + append_images:
|
| 242 |
+
# Get number of frames in this image
|
| 243 |
+
nfr = getattr(ims, "n_frames", 1)
|
| 244 |
+
|
| 245 |
+
for idx in range(nfr):
|
| 246 |
+
ims.seek(idx)
|
| 247 |
+
|
| 248 |
+
# Make sure image mode is supported
|
| 249 |
+
frame = ims
|
| 250 |
+
rawmode = ims.mode
|
| 251 |
+
if ims.mode not in {"RGB", "RGBA"}:
|
| 252 |
+
rawmode = "RGBA" if ims.has_transparency_data else "RGB"
|
| 253 |
+
frame = ims.convert(rawmode)
|
| 254 |
+
|
| 255 |
+
# Update frame duration
|
| 256 |
+
if isinstance(duration, (list, tuple)):
|
| 257 |
+
frame_duration = duration[frame_idx]
|
| 258 |
+
else:
|
| 259 |
+
frame_duration = duration
|
| 260 |
+
|
| 261 |
+
# Append the frame to the animation encoder
|
| 262 |
+
enc.add(
|
| 263 |
+
frame.tobytes("raw", rawmode),
|
| 264 |
+
frame_duration,
|
| 265 |
+
frame.size,
|
| 266 |
+
rawmode,
|
| 267 |
+
is_single_frame,
|
| 268 |
+
)
|
| 269 |
+
|
| 270 |
+
# Update frame index
|
| 271 |
+
frame_idx += 1
|
| 272 |
+
|
| 273 |
+
if not save_all:
|
| 274 |
+
break
|
| 275 |
+
|
| 276 |
+
finally:
|
| 277 |
+
im.seek(cur_idx)
|
| 278 |
+
|
| 279 |
+
# Get the final output from the encoder
|
| 280 |
+
data = enc.finish()
|
| 281 |
+
if data is None:
|
| 282 |
+
msg = "cannot write file as AVIF (encoder returned None)"
|
| 283 |
+
raise OSError(msg)
|
| 284 |
+
|
| 285 |
+
fp.write(data)
|
| 286 |
+
|
| 287 |
+
|
| 288 |
+
Image.register_open(AvifImageFile.format, AvifImageFile, _accept)
|
| 289 |
+
if SUPPORTED:
|
| 290 |
+
Image.register_save(AvifImageFile.format, _save)
|
| 291 |
+
Image.register_save_all(AvifImageFile.format, _save_all)
|
| 292 |
+
Image.register_extensions(AvifImageFile.format, [".avif", ".avifs"])
|
| 293 |
+
Image.register_mime(AvifImageFile.format, "image/avif")
|
.venv/lib/python3.12/site-packages/PIL/FliImagePlugin.py
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# The Python Imaging Library.
|
| 3 |
+
# $Id$
|
| 4 |
+
#
|
| 5 |
+
# FLI/FLC file handling.
|
| 6 |
+
#
|
| 7 |
+
# History:
|
| 8 |
+
# 95-09-01 fl Created
|
| 9 |
+
# 97-01-03 fl Fixed parser, setup decoder tile
|
| 10 |
+
# 98-07-15 fl Renamed offset attribute to avoid name clash
|
| 11 |
+
#
|
| 12 |
+
# Copyright (c) Secret Labs AB 1997-98.
|
| 13 |
+
# Copyright (c) Fredrik Lundh 1995-97.
|
| 14 |
+
#
|
| 15 |
+
# See the README file for information on usage and redistribution.
|
| 16 |
+
#
|
| 17 |
+
from __future__ import annotations
|
| 18 |
+
|
| 19 |
+
import os
|
| 20 |
+
|
| 21 |
+
from . import Image, ImageFile, ImagePalette
|
| 22 |
+
from ._binary import i16le as i16
|
| 23 |
+
from ._binary import i32le as i32
|
| 24 |
+
from ._binary import o8
|
| 25 |
+
from ._util import DeferredError
|
| 26 |
+
|
| 27 |
+
#
|
| 28 |
+
# decoder
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def _accept(prefix: bytes) -> bool:
|
| 32 |
+
return (
|
| 33 |
+
len(prefix) >= 16
|
| 34 |
+
and i16(prefix, 4) in [0xAF11, 0xAF12]
|
| 35 |
+
and i16(prefix, 14) in [0, 3] # flags
|
| 36 |
+
)
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
##
|
| 40 |
+
# Image plugin for the FLI/FLC animation format. Use the <b>seek</b>
|
| 41 |
+
# method to load individual frames.
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
class FliImageFile(ImageFile.ImageFile):
|
| 45 |
+
format = "FLI"
|
| 46 |
+
format_description = "Autodesk FLI/FLC Animation"
|
| 47 |
+
_close_exclusive_fp_after_loading = False
|
| 48 |
+
|
| 49 |
+
def _open(self) -> None:
|
| 50 |
+
# HEAD
|
| 51 |
+
assert self.fp is not None
|
| 52 |
+
s = self.fp.read(128)
|
| 53 |
+
if not (
|
| 54 |
+
_accept(s)
|
| 55 |
+
and s[20:22] == b"\x00" * 2
|
| 56 |
+
and s[42:80] == b"\x00" * 38
|
| 57 |
+
and s[88:] == b"\x00" * 40
|
| 58 |
+
):
|
| 59 |
+
msg = "not an FLI/FLC file"
|
| 60 |
+
raise SyntaxError(msg)
|
| 61 |
+
|
| 62 |
+
# frames
|
| 63 |
+
self.n_frames = i16(s, 6)
|
| 64 |
+
self.is_animated = self.n_frames > 1
|
| 65 |
+
|
| 66 |
+
# image characteristics
|
| 67 |
+
self._mode = "P"
|
| 68 |
+
self._size = i16(s, 8), i16(s, 10)
|
| 69 |
+
|
| 70 |
+
# animation speed
|
| 71 |
+
duration = i32(s, 16)
|
| 72 |
+
magic = i16(s, 4)
|
| 73 |
+
if magic == 0xAF11:
|
| 74 |
+
duration = (duration * 1000) // 70
|
| 75 |
+
self.info["duration"] = duration
|
| 76 |
+
|
| 77 |
+
# look for palette
|
| 78 |
+
palette = [(a, a, a) for a in range(256)]
|
| 79 |
+
|
| 80 |
+
s = self.fp.read(16)
|
| 81 |
+
|
| 82 |
+
self.__offset = 128
|
| 83 |
+
|
| 84 |
+
if i16(s, 4) == 0xF100:
|
| 85 |
+
# prefix chunk; ignore it
|
| 86 |
+
self.fp.seek(self.__offset + i32(s))
|
| 87 |
+
s = self.fp.read(16)
|
| 88 |
+
|
| 89 |
+
if i16(s, 4) == 0xF1FA:
|
| 90 |
+
# look for palette chunk
|
| 91 |
+
number_of_subchunks = i16(s, 6)
|
| 92 |
+
chunk_size: int | None = None
|
| 93 |
+
for _ in range(number_of_subchunks):
|
| 94 |
+
if chunk_size is not None:
|
| 95 |
+
self.fp.seek(chunk_size - 6, os.SEEK_CUR)
|
| 96 |
+
s = self.fp.read(6)
|
| 97 |
+
chunk_type = i16(s, 4)
|
| 98 |
+
if chunk_type in (4, 11):
|
| 99 |
+
self._palette(palette, 2 if chunk_type == 11 else 0)
|
| 100 |
+
break
|
| 101 |
+
chunk_size = i32(s)
|
| 102 |
+
if not chunk_size:
|
| 103 |
+
break
|
| 104 |
+
|
| 105 |
+
self.palette = ImagePalette.raw(
|
| 106 |
+
"RGB", b"".join(o8(r) + o8(g) + o8(b) for (r, g, b) in palette)
|
| 107 |
+
)
|
| 108 |
+
|
| 109 |
+
# set things up to decode first frame
|
| 110 |
+
self.__frame = -1
|
| 111 |
+
self._fp = self.fp
|
| 112 |
+
self.__rewind = self.fp.tell()
|
| 113 |
+
self.seek(0)
|
| 114 |
+
|
| 115 |
+
def _palette(self, palette: list[tuple[int, int, int]], shift: int) -> None:
|
| 116 |
+
# load palette
|
| 117 |
+
|
| 118 |
+
i = 0
|
| 119 |
+
assert self.fp is not None
|
| 120 |
+
for e in range(i16(self.fp.read(2))):
|
| 121 |
+
s = self.fp.read(2)
|
| 122 |
+
i = i + s[0]
|
| 123 |
+
n = s[1]
|
| 124 |
+
if n == 0:
|
| 125 |
+
n = 256
|
| 126 |
+
s = self.fp.read(n * 3)
|
| 127 |
+
for n in range(0, len(s), 3):
|
| 128 |
+
r = s[n] << shift
|
| 129 |
+
g = s[n + 1] << shift
|
| 130 |
+
b = s[n + 2] << shift
|
| 131 |
+
palette[i] = (r, g, b)
|
| 132 |
+
i += 1
|
| 133 |
+
|
| 134 |
+
def seek(self, frame: int) -> None:
|
| 135 |
+
if not self._seek_check(frame):
|
| 136 |
+
return
|
| 137 |
+
if frame < self.__frame:
|
| 138 |
+
self._seek(0)
|
| 139 |
+
|
| 140 |
+
for f in range(self.__frame + 1, frame + 1):
|
| 141 |
+
self._seek(f)
|
| 142 |
+
|
| 143 |
+
def _seek(self, frame: int) -> None:
|
| 144 |
+
if isinstance(self._fp, DeferredError):
|
| 145 |
+
raise self._fp.ex
|
| 146 |
+
if frame == 0:
|
| 147 |
+
self.__frame = -1
|
| 148 |
+
self._fp.seek(self.__rewind)
|
| 149 |
+
self.__offset = 128
|
| 150 |
+
else:
|
| 151 |
+
# ensure that the previous frame was loaded
|
| 152 |
+
self.load()
|
| 153 |
+
|
| 154 |
+
if frame != self.__frame + 1:
|
| 155 |
+
msg = f"cannot seek to frame {frame}"
|
| 156 |
+
raise ValueError(msg)
|
| 157 |
+
self.__frame = frame
|
| 158 |
+
|
| 159 |
+
# move to next frame
|
| 160 |
+
self.fp = self._fp
|
| 161 |
+
self.fp.seek(self.__offset)
|
| 162 |
+
|
| 163 |
+
s = self.fp.read(4)
|
| 164 |
+
if not s:
|
| 165 |
+
msg = "missing frame size"
|
| 166 |
+
raise EOFError(msg)
|
| 167 |
+
|
| 168 |
+
framesize = i32(s)
|
| 169 |
+
|
| 170 |
+
self.decodermaxblock = framesize
|
| 171 |
+
self.tile = [ImageFile._Tile("fli", (0, 0) + self.size, self.__offset)]
|
| 172 |
+
|
| 173 |
+
self.__offset += framesize
|
| 174 |
+
|
| 175 |
+
def tell(self) -> int:
|
| 176 |
+
return self.__frame
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
#
|
| 180 |
+
# registry
|
| 181 |
+
|
| 182 |
+
Image.register_open(FliImageFile.format, FliImageFile, _accept)
|
| 183 |
+
|
| 184 |
+
Image.register_extensions(FliImageFile.format, [".fli", ".flc"])
|
.venv/lib/python3.12/site-packages/PIL/FpxImagePlugin.py
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# THIS IS WORK IN PROGRESS
|
| 3 |
+
#
|
| 4 |
+
# The Python Imaging Library.
|
| 5 |
+
# $Id$
|
| 6 |
+
#
|
| 7 |
+
# FlashPix support for PIL
|
| 8 |
+
#
|
| 9 |
+
# History:
|
| 10 |
+
# 97-01-25 fl Created (reads uncompressed RGB images only)
|
| 11 |
+
#
|
| 12 |
+
# Copyright (c) Secret Labs AB 1997.
|
| 13 |
+
# Copyright (c) Fredrik Lundh 1997.
|
| 14 |
+
#
|
| 15 |
+
# See the README file for information on usage and redistribution.
|
| 16 |
+
#
|
| 17 |
+
from __future__ import annotations
|
| 18 |
+
|
| 19 |
+
import olefile
|
| 20 |
+
|
| 21 |
+
from . import Image, ImageFile
|
| 22 |
+
from ._binary import i32le as i32
|
| 23 |
+
|
| 24 |
+
# we map from colour field tuples to (mode, rawmode) descriptors
|
| 25 |
+
MODES = {
|
| 26 |
+
# opacity
|
| 27 |
+
(0x00007FFE,): ("A", "L"),
|
| 28 |
+
# monochrome
|
| 29 |
+
(0x00010000,): ("L", "L"),
|
| 30 |
+
(0x00018000, 0x00017FFE): ("RGBA", "LA"),
|
| 31 |
+
# photo YCC
|
| 32 |
+
(0x00020000, 0x00020001, 0x00020002): ("RGB", "YCC;P"),
|
| 33 |
+
(0x00028000, 0x00028001, 0x00028002, 0x00027FFE): ("RGBA", "YCCA;P"),
|
| 34 |
+
# standard RGB (NIFRGB)
|
| 35 |
+
(0x00030000, 0x00030001, 0x00030002): ("RGB", "RGB"),
|
| 36 |
+
(0x00038000, 0x00038001, 0x00038002, 0x00037FFE): ("RGBA", "RGBA"),
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
#
|
| 41 |
+
# --------------------------------------------------------------------
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def _accept(prefix: bytes) -> bool:
|
| 45 |
+
return prefix.startswith(olefile.MAGIC)
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
##
|
| 49 |
+
# Image plugin for the FlashPix images.
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
class FpxImageFile(ImageFile.ImageFile):
|
| 53 |
+
format = "FPX"
|
| 54 |
+
format_description = "FlashPix"
|
| 55 |
+
|
| 56 |
+
def _open(self) -> None:
|
| 57 |
+
#
|
| 58 |
+
# read the OLE directory and see if this is a likely
|
| 59 |
+
# to be a FlashPix file
|
| 60 |
+
|
| 61 |
+
assert self.fp is not None
|
| 62 |
+
try:
|
| 63 |
+
self.ole = olefile.OleFileIO(self.fp)
|
| 64 |
+
except OSError as e:
|
| 65 |
+
msg = "not an FPX file; invalid OLE file"
|
| 66 |
+
raise SyntaxError(msg) from e
|
| 67 |
+
|
| 68 |
+
root = self.ole.root
|
| 69 |
+
if not root or root.clsid != "56616700-C154-11CE-8553-00AA00A1F95B":
|
| 70 |
+
msg = "not an FPX file; bad root CLSID"
|
| 71 |
+
raise SyntaxError(msg)
|
| 72 |
+
|
| 73 |
+
self._open_index(1)
|
| 74 |
+
|
| 75 |
+
def _open_index(self, index: int = 1) -> None:
|
| 76 |
+
#
|
| 77 |
+
# get the Image Contents Property Set
|
| 78 |
+
|
| 79 |
+
prop = self.ole.getproperties(
|
| 80 |
+
[f"Data Object Store {index:06d}", "\005Image Contents"]
|
| 81 |
+
)
|
| 82 |
+
|
| 83 |
+
# size (highest resolution)
|
| 84 |
+
|
| 85 |
+
assert isinstance(prop[0x1000002], int)
|
| 86 |
+
assert isinstance(prop[0x1000003], int)
|
| 87 |
+
self._size = prop[0x1000002], prop[0x1000003]
|
| 88 |
+
|
| 89 |
+
size = max(self.size)
|
| 90 |
+
i = 1
|
| 91 |
+
while size > 64:
|
| 92 |
+
size = size // 2
|
| 93 |
+
i += 1
|
| 94 |
+
self.maxid = i - 1
|
| 95 |
+
|
| 96 |
+
# mode. instead of using a single field for this, flashpix
|
| 97 |
+
# requires you to specify the mode for each channel in each
|
| 98 |
+
# resolution subimage, and leaves it to the decoder to make
|
| 99 |
+
# sure that they all match. for now, we'll cheat and assume
|
| 100 |
+
# that this is always the case.
|
| 101 |
+
|
| 102 |
+
id = self.maxid << 16
|
| 103 |
+
|
| 104 |
+
s = prop[0x2000002 | id]
|
| 105 |
+
|
| 106 |
+
if not isinstance(s, bytes) or (bands := i32(s, 4)) > 4:
|
| 107 |
+
msg = "Invalid number of bands"
|
| 108 |
+
raise OSError(msg)
|
| 109 |
+
|
| 110 |
+
# note: for now, we ignore the "uncalibrated" flag
|
| 111 |
+
colors = tuple(i32(s, 8 + i * 4) & 0x7FFFFFFF for i in range(bands))
|
| 112 |
+
|
| 113 |
+
self._mode, self.rawmode = MODES[colors]
|
| 114 |
+
|
| 115 |
+
# load JPEG tables, if any
|
| 116 |
+
self.jpeg = {}
|
| 117 |
+
for i in range(256):
|
| 118 |
+
id = 0x3000001 | (i << 16)
|
| 119 |
+
if id in prop:
|
| 120 |
+
self.jpeg[i] = prop[id]
|
| 121 |
+
|
| 122 |
+
self._open_subimage(1, self.maxid)
|
| 123 |
+
|
| 124 |
+
def _open_subimage(self, index: int = 1, subimage: int = 0) -> None:
|
| 125 |
+
#
|
| 126 |
+
# setup tile descriptors for a given subimage
|
| 127 |
+
|
| 128 |
+
stream = [
|
| 129 |
+
f"Data Object Store {index:06d}",
|
| 130 |
+
f"Resolution {subimage:04d}",
|
| 131 |
+
"Subimage 0000 Header",
|
| 132 |
+
]
|
| 133 |
+
|
| 134 |
+
fp = self.ole.openstream(stream)
|
| 135 |
+
|
| 136 |
+
# skip prefix
|
| 137 |
+
fp.read(28)
|
| 138 |
+
|
| 139 |
+
# header stream
|
| 140 |
+
s = fp.read(36)
|
| 141 |
+
|
| 142 |
+
size = i32(s, 4), i32(s, 8)
|
| 143 |
+
# tilecount = i32(s, 12)
|
| 144 |
+
xtile, ytile = i32(s, 16), i32(s, 20)
|
| 145 |
+
# channels = i32(s, 24)
|
| 146 |
+
offset = i32(s, 28)
|
| 147 |
+
length = i32(s, 32)
|
| 148 |
+
|
| 149 |
+
if size != self.size:
|
| 150 |
+
msg = "subimage mismatch"
|
| 151 |
+
raise OSError(msg)
|
| 152 |
+
|
| 153 |
+
# get tile descriptors
|
| 154 |
+
fp.seek(28 + offset)
|
| 155 |
+
s = fp.read(i32(s, 12) * length)
|
| 156 |
+
|
| 157 |
+
x = y = 0
|
| 158 |
+
xsize, ysize = size
|
| 159 |
+
self.tile = []
|
| 160 |
+
|
| 161 |
+
for i in range(0, len(s), length):
|
| 162 |
+
x1 = min(xsize, x + xtile)
|
| 163 |
+
y1 = min(ysize, y + ytile)
|
| 164 |
+
|
| 165 |
+
compression = i32(s, i + 8)
|
| 166 |
+
|
| 167 |
+
if compression == 0:
|
| 168 |
+
self.tile.append(
|
| 169 |
+
ImageFile._Tile(
|
| 170 |
+
"raw",
|
| 171 |
+
(x, y, x1, y1),
|
| 172 |
+
i32(s, i) + 28,
|
| 173 |
+
self.rawmode,
|
| 174 |
+
)
|
| 175 |
+
)
|
| 176 |
+
|
| 177 |
+
elif compression == 1:
|
| 178 |
+
# FIXME: the fill decoder is not implemented
|
| 179 |
+
self.tile.append(
|
| 180 |
+
ImageFile._Tile(
|
| 181 |
+
"fill",
|
| 182 |
+
(x, y, x1, y1),
|
| 183 |
+
i32(s, i) + 28,
|
| 184 |
+
(self.rawmode, s[12:16]),
|
| 185 |
+
)
|
| 186 |
+
)
|
| 187 |
+
|
| 188 |
+
elif compression == 2:
|
| 189 |
+
internal_color_conversion = s[14]
|
| 190 |
+
jpeg_tables = s[15]
|
| 191 |
+
rawmode = self.rawmode
|
| 192 |
+
|
| 193 |
+
if internal_color_conversion:
|
| 194 |
+
# The image is stored as usual (usually YCbCr).
|
| 195 |
+
if rawmode == "RGBA":
|
| 196 |
+
# For "RGBA", data is stored as YCbCrA based on
|
| 197 |
+
# negative RGB. The following trick works around
|
| 198 |
+
# this problem :
|
| 199 |
+
jpegmode, rawmode = "YCbCrK", "CMYK"
|
| 200 |
+
else:
|
| 201 |
+
jpegmode = None # let the decoder decide
|
| 202 |
+
|
| 203 |
+
else:
|
| 204 |
+
# The image is stored as defined by rawmode
|
| 205 |
+
jpegmode = rawmode
|
| 206 |
+
|
| 207 |
+
self.tile.append(
|
| 208 |
+
ImageFile._Tile(
|
| 209 |
+
"jpeg",
|
| 210 |
+
(x, y, x1, y1),
|
| 211 |
+
i32(s, i) + 28,
|
| 212 |
+
(rawmode, jpegmode),
|
| 213 |
+
)
|
| 214 |
+
)
|
| 215 |
+
|
| 216 |
+
# FIXME: jpeg tables are tile dependent; the prefix
|
| 217 |
+
# data must be placed in the tile descriptor itself!
|
| 218 |
+
|
| 219 |
+
if jpeg_tables:
|
| 220 |
+
self.tile_prefix = self.jpeg[jpeg_tables]
|
| 221 |
+
|
| 222 |
+
else:
|
| 223 |
+
msg = "unknown/invalid compression"
|
| 224 |
+
raise OSError(msg)
|
| 225 |
+
|
| 226 |
+
x += xtile
|
| 227 |
+
if x >= xsize:
|
| 228 |
+
x, y = 0, y + ytile
|
| 229 |
+
if y >= ysize:
|
| 230 |
+
break # isn't really required
|
| 231 |
+
|
| 232 |
+
assert self.fp is not None
|
| 233 |
+
self.stream = stream
|
| 234 |
+
self._fp = self.fp
|
| 235 |
+
self.fp = None
|
| 236 |
+
|
| 237 |
+
def load(self) -> Image.core.PixelAccess | None:
|
| 238 |
+
if not self.fp:
|
| 239 |
+
self.fp = self.ole.openstream(self.stream[:2] + ["Subimage 0000 Data"])
|
| 240 |
+
|
| 241 |
+
return ImageFile.ImageFile.load(self)
|
| 242 |
+
|
| 243 |
+
def close(self) -> None:
|
| 244 |
+
self.ole.close()
|
| 245 |
+
super().close()
|
| 246 |
+
|
| 247 |
+
def __exit__(self, *args: object) -> None:
|
| 248 |
+
self.ole.close()
|
| 249 |
+
super().__exit__()
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
#
|
| 253 |
+
# --------------------------------------------------------------------
|
| 254 |
+
|
| 255 |
+
|
| 256 |
+
Image.register_open(FpxImageFile.format, FpxImageFile, _accept)
|
| 257 |
+
|
| 258 |
+
Image.register_extension(FpxImageFile.format, ".fpx")
|
.venv/lib/python3.12/site-packages/PIL/ImageChops.py
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# The Python Imaging Library.
|
| 3 |
+
# $Id$
|
| 4 |
+
#
|
| 5 |
+
# standard channel operations
|
| 6 |
+
#
|
| 7 |
+
# History:
|
| 8 |
+
# 1996-03-24 fl Created
|
| 9 |
+
# 1996-08-13 fl Added logical operations (for "1" images)
|
| 10 |
+
# 2000-10-12 fl Added offset method (from Image.py)
|
| 11 |
+
#
|
| 12 |
+
# Copyright (c) 1997-2000 by Secret Labs AB
|
| 13 |
+
# Copyright (c) 1996-2000 by Fredrik Lundh
|
| 14 |
+
#
|
| 15 |
+
# See the README file for information on usage and redistribution.
|
| 16 |
+
#
|
| 17 |
+
|
| 18 |
+
from __future__ import annotations
|
| 19 |
+
|
| 20 |
+
from . import Image
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def constant(image: Image.Image, value: int) -> Image.Image:
|
| 24 |
+
"""Fill a channel with a given gray level.
|
| 25 |
+
|
| 26 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 27 |
+
"""
|
| 28 |
+
|
| 29 |
+
return Image.new("L", image.size, value)
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def duplicate(image: Image.Image) -> Image.Image:
|
| 33 |
+
"""Copy a channel. Alias for :py:meth:`PIL.Image.Image.copy`.
|
| 34 |
+
|
| 35 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 36 |
+
"""
|
| 37 |
+
|
| 38 |
+
return image.copy()
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def invert(image: Image.Image) -> Image.Image:
|
| 42 |
+
"""
|
| 43 |
+
Invert an image (channel). ::
|
| 44 |
+
|
| 45 |
+
out = MAX - image
|
| 46 |
+
|
| 47 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 48 |
+
"""
|
| 49 |
+
|
| 50 |
+
image.load()
|
| 51 |
+
return image._new(image.im.chop_invert())
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
def lighter(image1: Image.Image, image2: Image.Image) -> Image.Image:
|
| 55 |
+
"""
|
| 56 |
+
Compares the two images, pixel by pixel, and returns a new image containing
|
| 57 |
+
the lighter values. ::
|
| 58 |
+
|
| 59 |
+
out = max(image1, image2)
|
| 60 |
+
|
| 61 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 62 |
+
"""
|
| 63 |
+
|
| 64 |
+
image1.load()
|
| 65 |
+
image2.load()
|
| 66 |
+
return image1._new(image1.im.chop_lighter(image2.im))
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def darker(image1: Image.Image, image2: Image.Image) -> Image.Image:
|
| 70 |
+
"""
|
| 71 |
+
Compares the two images, pixel by pixel, and returns a new image containing
|
| 72 |
+
the darker values. ::
|
| 73 |
+
|
| 74 |
+
out = min(image1, image2)
|
| 75 |
+
|
| 76 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 77 |
+
"""
|
| 78 |
+
|
| 79 |
+
image1.load()
|
| 80 |
+
image2.load()
|
| 81 |
+
return image1._new(image1.im.chop_darker(image2.im))
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
def difference(image1: Image.Image, image2: Image.Image) -> Image.Image:
|
| 85 |
+
"""
|
| 86 |
+
Returns the absolute value of the pixel-by-pixel difference between the two
|
| 87 |
+
images. ::
|
| 88 |
+
|
| 89 |
+
out = abs(image1 - image2)
|
| 90 |
+
|
| 91 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 92 |
+
"""
|
| 93 |
+
|
| 94 |
+
image1.load()
|
| 95 |
+
image2.load()
|
| 96 |
+
return image1._new(image1.im.chop_difference(image2.im))
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
def multiply(image1: Image.Image, image2: Image.Image) -> Image.Image:
|
| 100 |
+
"""
|
| 101 |
+
Superimposes two images on top of each other.
|
| 102 |
+
|
| 103 |
+
If you multiply an image with a solid black image, the result is black. If
|
| 104 |
+
you multiply with a solid white image, the image is unaffected. ::
|
| 105 |
+
|
| 106 |
+
out = image1 * image2 / MAX
|
| 107 |
+
|
| 108 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 109 |
+
"""
|
| 110 |
+
|
| 111 |
+
image1.load()
|
| 112 |
+
image2.load()
|
| 113 |
+
return image1._new(image1.im.chop_multiply(image2.im))
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
def screen(image1: Image.Image, image2: Image.Image) -> Image.Image:
|
| 117 |
+
"""
|
| 118 |
+
Superimposes two inverted images on top of each other. ::
|
| 119 |
+
|
| 120 |
+
out = MAX - ((MAX - image1) * (MAX - image2) / MAX)
|
| 121 |
+
|
| 122 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 123 |
+
"""
|
| 124 |
+
|
| 125 |
+
image1.load()
|
| 126 |
+
image2.load()
|
| 127 |
+
return image1._new(image1.im.chop_screen(image2.im))
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
def soft_light(image1: Image.Image, image2: Image.Image) -> Image.Image:
|
| 131 |
+
"""
|
| 132 |
+
Superimposes two images on top of each other using the Soft Light algorithm
|
| 133 |
+
|
| 134 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 135 |
+
"""
|
| 136 |
+
|
| 137 |
+
image1.load()
|
| 138 |
+
image2.load()
|
| 139 |
+
return image1._new(image1.im.chop_soft_light(image2.im))
|
| 140 |
+
|
| 141 |
+
|
| 142 |
+
def hard_light(image1: Image.Image, image2: Image.Image) -> Image.Image:
|
| 143 |
+
"""
|
| 144 |
+
Superimposes two images on top of each other using the Hard Light algorithm
|
| 145 |
+
|
| 146 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 147 |
+
"""
|
| 148 |
+
|
| 149 |
+
image1.load()
|
| 150 |
+
image2.load()
|
| 151 |
+
return image1._new(image1.im.chop_hard_light(image2.im))
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
def overlay(image1: Image.Image, image2: Image.Image) -> Image.Image:
|
| 155 |
+
"""
|
| 156 |
+
Superimposes two images on top of each other using the Overlay algorithm
|
| 157 |
+
|
| 158 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 159 |
+
"""
|
| 160 |
+
|
| 161 |
+
image1.load()
|
| 162 |
+
image2.load()
|
| 163 |
+
return image1._new(image1.im.chop_overlay(image2.im))
|
| 164 |
+
|
| 165 |
+
|
| 166 |
+
def add(
|
| 167 |
+
image1: Image.Image, image2: Image.Image, scale: float = 1.0, offset: float = 0
|
| 168 |
+
) -> Image.Image:
|
| 169 |
+
"""
|
| 170 |
+
Adds two images, dividing the result by scale and adding the
|
| 171 |
+
offset. If omitted, scale defaults to 1.0, and offset to 0.0. ::
|
| 172 |
+
|
| 173 |
+
out = ((image1 + image2) / scale + offset)
|
| 174 |
+
|
| 175 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 176 |
+
"""
|
| 177 |
+
|
| 178 |
+
image1.load()
|
| 179 |
+
image2.load()
|
| 180 |
+
return image1._new(image1.im.chop_add(image2.im, scale, offset))
|
| 181 |
+
|
| 182 |
+
|
| 183 |
+
def subtract(
|
| 184 |
+
image1: Image.Image, image2: Image.Image, scale: float = 1.0, offset: float = 0
|
| 185 |
+
) -> Image.Image:
|
| 186 |
+
"""
|
| 187 |
+
Subtracts two images, dividing the result by scale and adding the offset.
|
| 188 |
+
If omitted, scale defaults to 1.0, and offset to 0.0. ::
|
| 189 |
+
|
| 190 |
+
out = ((image1 - image2) / scale + offset)
|
| 191 |
+
|
| 192 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 193 |
+
"""
|
| 194 |
+
|
| 195 |
+
image1.load()
|
| 196 |
+
image2.load()
|
| 197 |
+
return image1._new(image1.im.chop_subtract(image2.im, scale, offset))
|
| 198 |
+
|
| 199 |
+
|
| 200 |
+
def add_modulo(image1: Image.Image, image2: Image.Image) -> Image.Image:
|
| 201 |
+
"""Add two images, without clipping the result. ::
|
| 202 |
+
|
| 203 |
+
out = ((image1 + image2) % MAX)
|
| 204 |
+
|
| 205 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 206 |
+
"""
|
| 207 |
+
|
| 208 |
+
image1.load()
|
| 209 |
+
image2.load()
|
| 210 |
+
return image1._new(image1.im.chop_add_modulo(image2.im))
|
| 211 |
+
|
| 212 |
+
|
| 213 |
+
def subtract_modulo(image1: Image.Image, image2: Image.Image) -> Image.Image:
|
| 214 |
+
"""Subtract two images, without clipping the result. ::
|
| 215 |
+
|
| 216 |
+
out = ((image1 - image2) % MAX)
|
| 217 |
+
|
| 218 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 219 |
+
"""
|
| 220 |
+
|
| 221 |
+
image1.load()
|
| 222 |
+
image2.load()
|
| 223 |
+
return image1._new(image1.im.chop_subtract_modulo(image2.im))
|
| 224 |
+
|
| 225 |
+
|
| 226 |
+
def logical_and(image1: Image.Image, image2: Image.Image) -> Image.Image:
|
| 227 |
+
"""Logical AND between two images.
|
| 228 |
+
|
| 229 |
+
Both of the images must have mode "1". If you would like to perform a
|
| 230 |
+
logical AND on an image with a mode other than "1", try
|
| 231 |
+
:py:meth:`~PIL.ImageChops.multiply` instead, using a black-and-white mask
|
| 232 |
+
as the second image. ::
|
| 233 |
+
|
| 234 |
+
out = ((image1 and image2) % MAX)
|
| 235 |
+
|
| 236 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 237 |
+
"""
|
| 238 |
+
|
| 239 |
+
image1.load()
|
| 240 |
+
image2.load()
|
| 241 |
+
return image1._new(image1.im.chop_and(image2.im))
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
def logical_or(image1: Image.Image, image2: Image.Image) -> Image.Image:
|
| 245 |
+
"""Logical OR between two images.
|
| 246 |
+
|
| 247 |
+
Both of the images must have mode "1". ::
|
| 248 |
+
|
| 249 |
+
out = ((image1 or image2) % MAX)
|
| 250 |
+
|
| 251 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 252 |
+
"""
|
| 253 |
+
|
| 254 |
+
image1.load()
|
| 255 |
+
image2.load()
|
| 256 |
+
return image1._new(image1.im.chop_or(image2.im))
|
| 257 |
+
|
| 258 |
+
|
| 259 |
+
def logical_xor(image1: Image.Image, image2: Image.Image) -> Image.Image:
|
| 260 |
+
"""Logical XOR between two images.
|
| 261 |
+
|
| 262 |
+
Both of the images must have mode "1". ::
|
| 263 |
+
|
| 264 |
+
out = ((bool(image1) != bool(image2)) % MAX)
|
| 265 |
+
|
| 266 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 267 |
+
"""
|
| 268 |
+
|
| 269 |
+
image1.load()
|
| 270 |
+
image2.load()
|
| 271 |
+
return image1._new(image1.im.chop_xor(image2.im))
|
| 272 |
+
|
| 273 |
+
|
| 274 |
+
def blend(image1: Image.Image, image2: Image.Image, alpha: float) -> Image.Image:
|
| 275 |
+
"""Blend images using constant transparency weight. Alias for
|
| 276 |
+
:py:func:`PIL.Image.blend`.
|
| 277 |
+
|
| 278 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 279 |
+
"""
|
| 280 |
+
|
| 281 |
+
return Image.blend(image1, image2, alpha)
|
| 282 |
+
|
| 283 |
+
|
| 284 |
+
def composite(
|
| 285 |
+
image1: Image.Image, image2: Image.Image, mask: Image.Image
|
| 286 |
+
) -> Image.Image:
|
| 287 |
+
"""Create composite using transparency mask. Alias for
|
| 288 |
+
:py:func:`PIL.Image.composite`.
|
| 289 |
+
|
| 290 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 291 |
+
"""
|
| 292 |
+
|
| 293 |
+
return Image.composite(image1, image2, mask)
|
| 294 |
+
|
| 295 |
+
|
| 296 |
+
def offset(image: Image.Image, xoffset: int, yoffset: int | None = None) -> Image.Image:
|
| 297 |
+
"""Returns a copy of the image where data has been offset by the given
|
| 298 |
+
distances. Data wraps around the edges. If ``yoffset`` is omitted, it
|
| 299 |
+
is assumed to be equal to ``xoffset``.
|
| 300 |
+
|
| 301 |
+
:param image: Input image.
|
| 302 |
+
:param xoffset: The horizontal distance.
|
| 303 |
+
:param yoffset: The vertical distance. If omitted, both
|
| 304 |
+
distances are set to the same value.
|
| 305 |
+
:rtype: :py:class:`~PIL.Image.Image`
|
| 306 |
+
"""
|
| 307 |
+
|
| 308 |
+
if yoffset is None:
|
| 309 |
+
yoffset = xoffset
|
| 310 |
+
image.load()
|
| 311 |
+
return image._new(image.im.offset(xoffset, yoffset))
|
.venv/lib/python3.12/site-packages/PIL/ImageSequence.py
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# The Python Imaging Library.
|
| 3 |
+
# $Id$
|
| 4 |
+
#
|
| 5 |
+
# sequence support classes
|
| 6 |
+
#
|
| 7 |
+
# history:
|
| 8 |
+
# 1997-02-20 fl Created
|
| 9 |
+
#
|
| 10 |
+
# Copyright (c) 1997 by Secret Labs AB.
|
| 11 |
+
# Copyright (c) 1997 by Fredrik Lundh.
|
| 12 |
+
#
|
| 13 |
+
# See the README file for information on usage and redistribution.
|
| 14 |
+
#
|
| 15 |
+
|
| 16 |
+
##
|
| 17 |
+
from __future__ import annotations
|
| 18 |
+
|
| 19 |
+
from . import Image
|
| 20 |
+
|
| 21 |
+
TYPE_CHECKING = False
|
| 22 |
+
if TYPE_CHECKING:
|
| 23 |
+
from collections.abc import Callable
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
class Iterator:
|
| 27 |
+
"""
|
| 28 |
+
This class implements an iterator object that can be used to loop
|
| 29 |
+
over an image sequence.
|
| 30 |
+
|
| 31 |
+
You can use the ``[]`` operator to access elements by index. This operator
|
| 32 |
+
will raise an :py:exc:`IndexError` if you try to access a nonexistent
|
| 33 |
+
frame.
|
| 34 |
+
|
| 35 |
+
:param im: An image object.
|
| 36 |
+
"""
|
| 37 |
+
|
| 38 |
+
def __init__(self, im: Image.Image) -> None:
|
| 39 |
+
if not hasattr(im, "seek"):
|
| 40 |
+
msg = "im must have seek method"
|
| 41 |
+
raise AttributeError(msg)
|
| 42 |
+
self.im = im
|
| 43 |
+
self.position = getattr(self.im, "_min_frame", 0)
|
| 44 |
+
|
| 45 |
+
def __getitem__(self, ix: int) -> Image.Image:
|
| 46 |
+
try:
|
| 47 |
+
self.im.seek(ix)
|
| 48 |
+
return self.im
|
| 49 |
+
except EOFError as e:
|
| 50 |
+
msg = "end of sequence"
|
| 51 |
+
raise IndexError(msg) from e
|
| 52 |
+
|
| 53 |
+
def __iter__(self) -> Iterator:
|
| 54 |
+
return self
|
| 55 |
+
|
| 56 |
+
def __next__(self) -> Image.Image:
|
| 57 |
+
try:
|
| 58 |
+
self.im.seek(self.position)
|
| 59 |
+
self.position += 1
|
| 60 |
+
return self.im
|
| 61 |
+
except EOFError as e:
|
| 62 |
+
msg = "end of sequence"
|
| 63 |
+
raise StopIteration(msg) from e
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
def all_frames(
|
| 67 |
+
im: Image.Image | list[Image.Image],
|
| 68 |
+
func: Callable[[Image.Image], Image.Image] | None = None,
|
| 69 |
+
) -> list[Image.Image]:
|
| 70 |
+
"""
|
| 71 |
+
Applies a given function to all frames in an image or a list of images.
|
| 72 |
+
The frames are returned as a list of separate images.
|
| 73 |
+
|
| 74 |
+
:param im: An image, or a list of images.
|
| 75 |
+
:param func: The function to apply to all of the image frames.
|
| 76 |
+
:returns: A list of images.
|
| 77 |
+
"""
|
| 78 |
+
if not isinstance(im, list):
|
| 79 |
+
im = [im]
|
| 80 |
+
|
| 81 |
+
ims = []
|
| 82 |
+
for imSequence in im:
|
| 83 |
+
current = imSequence.tell()
|
| 84 |
+
|
| 85 |
+
ims += [im_frame.copy() for im_frame in Iterator(imSequence)]
|
| 86 |
+
|
| 87 |
+
imSequence.seek(current)
|
| 88 |
+
return [func(im) for im in ims] if func else ims
|
.venv/lib/python3.12/site-packages/PIL/ImageText.py
ADDED
|
@@ -0,0 +1,508 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import math
|
| 4 |
+
import re
|
| 5 |
+
from typing import AnyStr, Generic, NamedTuple
|
| 6 |
+
|
| 7 |
+
from . import ImageFont
|
| 8 |
+
from ._typing import _Ink
|
| 9 |
+
|
| 10 |
+
Font = ImageFont.ImageFont | ImageFont.FreeTypeFont | ImageFont.TransposedFont
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class _Line(NamedTuple):
|
| 14 |
+
x: float
|
| 15 |
+
y: float
|
| 16 |
+
anchor: str
|
| 17 |
+
text: str | bytes
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class _Wrap(Generic[AnyStr]):
|
| 21 |
+
lines: list[AnyStr] = []
|
| 22 |
+
position = 0
|
| 23 |
+
offset = 0
|
| 24 |
+
|
| 25 |
+
def __init__(
|
| 26 |
+
self,
|
| 27 |
+
text: Text[AnyStr],
|
| 28 |
+
width: int,
|
| 29 |
+
height: int | None = None,
|
| 30 |
+
font: Font | None = None,
|
| 31 |
+
) -> None:
|
| 32 |
+
self.text: Text[AnyStr] = text
|
| 33 |
+
self.width = width
|
| 34 |
+
self.height = height
|
| 35 |
+
self.font = font
|
| 36 |
+
|
| 37 |
+
input_text = self.text.text
|
| 38 |
+
emptystring = "" if isinstance(input_text, str) else b""
|
| 39 |
+
line = emptystring
|
| 40 |
+
|
| 41 |
+
for word in re.findall(
|
| 42 |
+
r"\s*\S+" if isinstance(input_text, str) else rb"\s*\S+", input_text
|
| 43 |
+
):
|
| 44 |
+
newlines = re.findall(
|
| 45 |
+
r"[^\S\n]*\n" if isinstance(input_text, str) else rb"[^\S\n]*\n", word
|
| 46 |
+
)
|
| 47 |
+
if newlines:
|
| 48 |
+
if not self.add_line(line):
|
| 49 |
+
break
|
| 50 |
+
for i, line in enumerate(newlines):
|
| 51 |
+
if i != 0 and not self.add_line(emptystring):
|
| 52 |
+
break
|
| 53 |
+
self.position += len(line)
|
| 54 |
+
word = word[len(line) :]
|
| 55 |
+
line = emptystring
|
| 56 |
+
|
| 57 |
+
new_line = line + word
|
| 58 |
+
if self.text._get_bbox(new_line, self.font)[2] <= width:
|
| 59 |
+
# This word fits on the line
|
| 60 |
+
line = new_line
|
| 61 |
+
continue
|
| 62 |
+
|
| 63 |
+
# This word does not fit on the line
|
| 64 |
+
if line and not self.add_line(line):
|
| 65 |
+
break
|
| 66 |
+
|
| 67 |
+
original_length = len(word)
|
| 68 |
+
word = word.lstrip()
|
| 69 |
+
self.offset = original_length - len(word)
|
| 70 |
+
|
| 71 |
+
if self.text._get_bbox(word, self.font)[2] > width:
|
| 72 |
+
if font is None:
|
| 73 |
+
msg = "Word does not fit within line"
|
| 74 |
+
raise ValueError(msg)
|
| 75 |
+
break
|
| 76 |
+
line = word
|
| 77 |
+
else:
|
| 78 |
+
if line:
|
| 79 |
+
self.add_line(line)
|
| 80 |
+
self.remaining_text: AnyStr = input_text[self.position :]
|
| 81 |
+
|
| 82 |
+
def add_line(self, line: AnyStr) -> bool:
|
| 83 |
+
lines = self.lines + [line]
|
| 84 |
+
if self.height is not None:
|
| 85 |
+
last_line_y = self.text._split(lines=lines)[-1].y
|
| 86 |
+
last_line_height = self.text._get_bbox(line, self.font)[3]
|
| 87 |
+
if last_line_y + last_line_height > self.height:
|
| 88 |
+
return False
|
| 89 |
+
|
| 90 |
+
self.lines = lines
|
| 91 |
+
self.position += len(line) + self.offset
|
| 92 |
+
self.offset = 0
|
| 93 |
+
return True
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
class Text(Generic[AnyStr]):
|
| 97 |
+
def __init__(
|
| 98 |
+
self,
|
| 99 |
+
text: AnyStr,
|
| 100 |
+
font: Font | None = None,
|
| 101 |
+
mode: str = "RGB",
|
| 102 |
+
spacing: float = 4,
|
| 103 |
+
direction: str | None = None,
|
| 104 |
+
features: list[str] | None = None,
|
| 105 |
+
language: str | None = None,
|
| 106 |
+
) -> None:
|
| 107 |
+
"""
|
| 108 |
+
:param text: String to be drawn.
|
| 109 |
+
:param font: Either an :py:class:`~PIL.ImageFont.ImageFont` instance,
|
| 110 |
+
:py:class:`~PIL.ImageFont.FreeTypeFont` instance,
|
| 111 |
+
:py:class:`~PIL.ImageFont.TransposedFont` instance or ``None``. If
|
| 112 |
+
``None``, the default font from :py:meth:`.ImageFont.load_default`
|
| 113 |
+
will be used.
|
| 114 |
+
:param mode: The image mode this will be used with.
|
| 115 |
+
:param spacing: The number of pixels between lines.
|
| 116 |
+
:param direction: Direction of the text. It can be ``"rtl"`` (right to left),
|
| 117 |
+
``"ltr"`` (left to right) or ``"ttb"`` (top to bottom).
|
| 118 |
+
Requires libraqm.
|
| 119 |
+
:param features: A list of OpenType font features to be used during text
|
| 120 |
+
layout. This is usually used to turn on optional font features
|
| 121 |
+
that are not enabled by default, for example ``"dlig"`` or
|
| 122 |
+
``"ss01"``, but can be also used to turn off default font
|
| 123 |
+
features, for example ``"-liga"`` to disable ligatures or
|
| 124 |
+
``"-kern"`` to disable kerning. To get all supported
|
| 125 |
+
features, see `OpenType docs`_.
|
| 126 |
+
Requires libraqm.
|
| 127 |
+
:param language: Language of the text. Different languages may use
|
| 128 |
+
different glyph shapes or ligatures. This parameter tells
|
| 129 |
+
the font which language the text is in, and to apply the
|
| 130 |
+
correct substitutions as appropriate, if available.
|
| 131 |
+
It should be a `BCP 47 language code`_.
|
| 132 |
+
Requires libraqm.
|
| 133 |
+
"""
|
| 134 |
+
self.text: AnyStr = text
|
| 135 |
+
self.font = font or ImageFont.load_default()
|
| 136 |
+
|
| 137 |
+
self.mode = mode
|
| 138 |
+
self.spacing = spacing
|
| 139 |
+
self.direction = direction
|
| 140 |
+
self.features = features
|
| 141 |
+
self.language = language
|
| 142 |
+
|
| 143 |
+
self.embedded_color = False
|
| 144 |
+
|
| 145 |
+
self.stroke_width: float = 0
|
| 146 |
+
self.stroke_fill: _Ink | None = None
|
| 147 |
+
|
| 148 |
+
def embed_color(self) -> None:
|
| 149 |
+
"""
|
| 150 |
+
Use embedded color glyphs (COLR, CBDT, SBIX).
|
| 151 |
+
"""
|
| 152 |
+
if self.mode not in ("RGB", "RGBA"):
|
| 153 |
+
msg = "Embedded color supported only in RGB and RGBA modes"
|
| 154 |
+
raise ValueError(msg)
|
| 155 |
+
self.embedded_color = True
|
| 156 |
+
|
| 157 |
+
def stroke(self, width: float = 0, fill: _Ink | None = None) -> None:
|
| 158 |
+
"""
|
| 159 |
+
:param width: The width of the text stroke.
|
| 160 |
+
:param fill: Color to use for the text stroke when drawing. If not given, will
|
| 161 |
+
default to the ``fill`` parameter from
|
| 162 |
+
:py:meth:`.ImageDraw.ImageDraw.text`.
|
| 163 |
+
"""
|
| 164 |
+
self.stroke_width = width
|
| 165 |
+
self.stroke_fill = fill
|
| 166 |
+
|
| 167 |
+
def _get_fontmode(self) -> str:
|
| 168 |
+
if self.mode in ("1", "P", "I", "F"):
|
| 169 |
+
return "1"
|
| 170 |
+
elif self.embedded_color:
|
| 171 |
+
return "RGBA"
|
| 172 |
+
else:
|
| 173 |
+
return "L"
|
| 174 |
+
|
| 175 |
+
def wrap(
|
| 176 |
+
self,
|
| 177 |
+
width: int,
|
| 178 |
+
height: int | None = None,
|
| 179 |
+
scaling: str | tuple[str, int] | None = None,
|
| 180 |
+
) -> Text[AnyStr] | None:
|
| 181 |
+
"""
|
| 182 |
+
Wrap text to fit within a given width.
|
| 183 |
+
|
| 184 |
+
:param width: The width to fit within.
|
| 185 |
+
:param height: An optional height limit. Any text that does not fit within this
|
| 186 |
+
will be returned as a new :py:class:`.Text` object.
|
| 187 |
+
:param scaling: An optional directive to scale the text, either "grow" as much
|
| 188 |
+
as possible within the given dimensions, or "shrink" until it
|
| 189 |
+
fits. It can also be a tuple of (direction, limit), with an
|
| 190 |
+
integer limit to stop scaling at.
|
| 191 |
+
|
| 192 |
+
:returns: An :py:class:`.Text` object, or None.
|
| 193 |
+
"""
|
| 194 |
+
if isinstance(self.font, ImageFont.TransposedFont):
|
| 195 |
+
msg = "TransposedFont not supported"
|
| 196 |
+
raise ValueError(msg)
|
| 197 |
+
if self.direction not in (None, "ltr"):
|
| 198 |
+
msg = "Only ltr direction supported"
|
| 199 |
+
raise ValueError(msg)
|
| 200 |
+
|
| 201 |
+
if scaling is None:
|
| 202 |
+
wrap = _Wrap(self, width, height)
|
| 203 |
+
else:
|
| 204 |
+
if not isinstance(self.font, ImageFont.FreeTypeFont):
|
| 205 |
+
msg = "'scaling' only supports FreeTypeFont"
|
| 206 |
+
raise ValueError(msg)
|
| 207 |
+
if height is None:
|
| 208 |
+
msg = "'scaling' requires 'height'"
|
| 209 |
+
raise ValueError(msg)
|
| 210 |
+
|
| 211 |
+
if isinstance(scaling, str):
|
| 212 |
+
limit = 1
|
| 213 |
+
else:
|
| 214 |
+
scaling, limit = scaling
|
| 215 |
+
|
| 216 |
+
font = self.font
|
| 217 |
+
wrap = _Wrap(self, width, height, font)
|
| 218 |
+
if scaling == "shrink":
|
| 219 |
+
if not wrap.remaining_text:
|
| 220 |
+
return None
|
| 221 |
+
|
| 222 |
+
size = math.ceil(font.size)
|
| 223 |
+
while wrap.remaining_text:
|
| 224 |
+
if size == max(limit, 1):
|
| 225 |
+
msg = "Text could not be scaled"
|
| 226 |
+
raise ValueError(msg)
|
| 227 |
+
size -= 1
|
| 228 |
+
font = self.font.font_variant(size=size)
|
| 229 |
+
wrap = _Wrap(self, width, height, font)
|
| 230 |
+
self.font = font
|
| 231 |
+
else:
|
| 232 |
+
if wrap.remaining_text:
|
| 233 |
+
msg = "Text could not be scaled"
|
| 234 |
+
raise ValueError(msg)
|
| 235 |
+
|
| 236 |
+
size = math.floor(font.size)
|
| 237 |
+
while not wrap.remaining_text:
|
| 238 |
+
if size == limit:
|
| 239 |
+
msg = "Text could not be scaled"
|
| 240 |
+
raise ValueError(msg)
|
| 241 |
+
size += 1
|
| 242 |
+
font = self.font.font_variant(size=size)
|
| 243 |
+
last_wrap = wrap
|
| 244 |
+
wrap = _Wrap(self, width, height, font)
|
| 245 |
+
size -= 1
|
| 246 |
+
if size != self.font.size:
|
| 247 |
+
self.font = self.font.font_variant(size=size)
|
| 248 |
+
wrap = last_wrap
|
| 249 |
+
|
| 250 |
+
if wrap.remaining_text:
|
| 251 |
+
text = Text(
|
| 252 |
+
text=wrap.remaining_text,
|
| 253 |
+
font=self.font,
|
| 254 |
+
mode=self.mode,
|
| 255 |
+
spacing=self.spacing,
|
| 256 |
+
direction=self.direction,
|
| 257 |
+
features=self.features,
|
| 258 |
+
language=self.language,
|
| 259 |
+
)
|
| 260 |
+
text.embedded_color = self.embedded_color
|
| 261 |
+
text.stroke_width = self.stroke_width
|
| 262 |
+
text.stroke_fill = self.stroke_fill
|
| 263 |
+
else:
|
| 264 |
+
text = None
|
| 265 |
+
|
| 266 |
+
newline = "\n" if isinstance(self.text, str) else b"\n"
|
| 267 |
+
self.text = newline.join(wrap.lines)
|
| 268 |
+
return text
|
| 269 |
+
|
| 270 |
+
def get_length(self) -> float:
|
| 271 |
+
"""
|
| 272 |
+
Returns length (in pixels with 1/64 precision) of text.
|
| 273 |
+
|
| 274 |
+
This is the amount by which following text should be offset.
|
| 275 |
+
Text bounding box may extend past the length in some fonts,
|
| 276 |
+
e.g. when using italics or accents.
|
| 277 |
+
|
| 278 |
+
The result is returned as a float; it is a whole number if using basic layout.
|
| 279 |
+
|
| 280 |
+
Note that the sum of two lengths may not equal the length of a concatenated
|
| 281 |
+
string due to kerning. If you need to adjust for kerning, include the following
|
| 282 |
+
character and subtract its length.
|
| 283 |
+
|
| 284 |
+
For example, instead of::
|
| 285 |
+
|
| 286 |
+
hello = ImageText.Text("Hello", font).get_length()
|
| 287 |
+
world = ImageText.Text("World", font).get_length()
|
| 288 |
+
helloworld = ImageText.Text("HelloWorld", font).get_length()
|
| 289 |
+
assert hello + world == helloworld
|
| 290 |
+
|
| 291 |
+
use::
|
| 292 |
+
|
| 293 |
+
hello = (
|
| 294 |
+
ImageText.Text("HelloW", font).get_length() -
|
| 295 |
+
ImageText.Text("W", font).get_length()
|
| 296 |
+
) # adjusted for kerning
|
| 297 |
+
world = ImageText.Text("World", font).get_length()
|
| 298 |
+
helloworld = ImageText.Text("HelloWorld", font).get_length()
|
| 299 |
+
assert hello + world == helloworld
|
| 300 |
+
|
| 301 |
+
or disable kerning with (requires libraqm)::
|
| 302 |
+
|
| 303 |
+
hello = ImageText.Text("Hello", font, features=["-kern"]).get_length()
|
| 304 |
+
world = ImageText.Text("World", font, features=["-kern"]).get_length()
|
| 305 |
+
helloworld = ImageText.Text(
|
| 306 |
+
"HelloWorld", font, features=["-kern"]
|
| 307 |
+
).get_length()
|
| 308 |
+
assert hello + world == helloworld
|
| 309 |
+
|
| 310 |
+
:return: Either width for horizontal text, or height for vertical text.
|
| 311 |
+
"""
|
| 312 |
+
if isinstance(self.text, str):
|
| 313 |
+
multiline = "\n" in self.text
|
| 314 |
+
else:
|
| 315 |
+
multiline = b"\n" in self.text
|
| 316 |
+
if multiline:
|
| 317 |
+
msg = "can't measure length of multiline text"
|
| 318 |
+
raise ValueError(msg)
|
| 319 |
+
return self.font.getlength(
|
| 320 |
+
self.text,
|
| 321 |
+
self._get_fontmode(),
|
| 322 |
+
self.direction,
|
| 323 |
+
self.features,
|
| 324 |
+
self.language,
|
| 325 |
+
)
|
| 326 |
+
|
| 327 |
+
def _split(
|
| 328 |
+
self,
|
| 329 |
+
xy: tuple[float, float] = (0, 0),
|
| 330 |
+
anchor: str | None = None,
|
| 331 |
+
align: str = "left",
|
| 332 |
+
lines: list[str] | list[bytes] | None = None,
|
| 333 |
+
) -> list[_Line]:
|
| 334 |
+
if anchor is None:
|
| 335 |
+
anchor = "lt" if self.direction == "ttb" else "la"
|
| 336 |
+
elif len(anchor) != 2:
|
| 337 |
+
msg = "anchor must be a 2 character string"
|
| 338 |
+
raise ValueError(msg)
|
| 339 |
+
|
| 340 |
+
if lines is None:
|
| 341 |
+
lines = (
|
| 342 |
+
self.text.split("\n")
|
| 343 |
+
if isinstance(self.text, str)
|
| 344 |
+
else self.text.split(b"\n")
|
| 345 |
+
)
|
| 346 |
+
if len(lines) == 1:
|
| 347 |
+
return [_Line(xy[0], xy[1], anchor, lines[0])]
|
| 348 |
+
|
| 349 |
+
if anchor[1] in "tb" and self.direction != "ttb":
|
| 350 |
+
msg = "anchor not supported for multiline text"
|
| 351 |
+
raise ValueError(msg)
|
| 352 |
+
|
| 353 |
+
fontmode = self._get_fontmode()
|
| 354 |
+
line_spacing = (
|
| 355 |
+
self.font.getbbox(
|
| 356 |
+
"A",
|
| 357 |
+
fontmode,
|
| 358 |
+
None,
|
| 359 |
+
self.features,
|
| 360 |
+
self.language,
|
| 361 |
+
self.stroke_width,
|
| 362 |
+
)[3]
|
| 363 |
+
+ self.stroke_width
|
| 364 |
+
+ self.spacing
|
| 365 |
+
)
|
| 366 |
+
|
| 367 |
+
top = xy[1]
|
| 368 |
+
parts = []
|
| 369 |
+
if self.direction == "ttb":
|
| 370 |
+
left = xy[0]
|
| 371 |
+
for line in lines:
|
| 372 |
+
parts.append(_Line(left, top, anchor, line))
|
| 373 |
+
left += line_spacing
|
| 374 |
+
else:
|
| 375 |
+
widths = []
|
| 376 |
+
max_width: float = 0
|
| 377 |
+
for line in lines:
|
| 378 |
+
line_width = self.font.getlength(
|
| 379 |
+
line, fontmode, self.direction, self.features, self.language
|
| 380 |
+
)
|
| 381 |
+
widths.append(line_width)
|
| 382 |
+
max_width = max(max_width, line_width)
|
| 383 |
+
|
| 384 |
+
if anchor[1] == "m":
|
| 385 |
+
top -= (len(lines) - 1) * line_spacing / 2.0
|
| 386 |
+
elif anchor[1] == "d":
|
| 387 |
+
top -= (len(lines) - 1) * line_spacing
|
| 388 |
+
|
| 389 |
+
idx = -1
|
| 390 |
+
for line in lines:
|
| 391 |
+
left = xy[0]
|
| 392 |
+
idx += 1
|
| 393 |
+
width_difference = max_width - widths[idx]
|
| 394 |
+
|
| 395 |
+
# align by align parameter
|
| 396 |
+
if align in ("left", "justify"):
|
| 397 |
+
pass
|
| 398 |
+
elif align == "center":
|
| 399 |
+
left += width_difference / 2.0
|
| 400 |
+
elif align == "right":
|
| 401 |
+
left += width_difference
|
| 402 |
+
else:
|
| 403 |
+
msg = 'align must be "left", "center", "right" or "justify"'
|
| 404 |
+
raise ValueError(msg)
|
| 405 |
+
|
| 406 |
+
if (
|
| 407 |
+
align == "justify"
|
| 408 |
+
and width_difference != 0
|
| 409 |
+
and idx != len(lines) - 1
|
| 410 |
+
):
|
| 411 |
+
words = (
|
| 412 |
+
line.split(" ") if isinstance(line, str) else line.split(b" ")
|
| 413 |
+
)
|
| 414 |
+
if len(words) > 1:
|
| 415 |
+
# align left by anchor
|
| 416 |
+
if anchor[0] == "m":
|
| 417 |
+
left -= max_width / 2.0
|
| 418 |
+
elif anchor[0] == "r":
|
| 419 |
+
left -= max_width
|
| 420 |
+
|
| 421 |
+
word_widths = [
|
| 422 |
+
self.font.getlength(
|
| 423 |
+
word,
|
| 424 |
+
fontmode,
|
| 425 |
+
self.direction,
|
| 426 |
+
self.features,
|
| 427 |
+
self.language,
|
| 428 |
+
)
|
| 429 |
+
for word in words
|
| 430 |
+
]
|
| 431 |
+
word_anchor = "l" + anchor[1]
|
| 432 |
+
width_difference = max_width - sum(word_widths)
|
| 433 |
+
i = 0
|
| 434 |
+
for word in words:
|
| 435 |
+
parts.append(_Line(left, top, word_anchor, word))
|
| 436 |
+
left += word_widths[i] + width_difference / (len(words) - 1)
|
| 437 |
+
i += 1
|
| 438 |
+
top += line_spacing
|
| 439 |
+
continue
|
| 440 |
+
|
| 441 |
+
# align left by anchor
|
| 442 |
+
if anchor[0] == "m":
|
| 443 |
+
left -= width_difference / 2.0
|
| 444 |
+
elif anchor[0] == "r":
|
| 445 |
+
left -= width_difference
|
| 446 |
+
parts.append(_Line(left, top, anchor, line))
|
| 447 |
+
top += line_spacing
|
| 448 |
+
|
| 449 |
+
return parts
|
| 450 |
+
|
| 451 |
+
def _get_bbox(
|
| 452 |
+
self, text: str | bytes, font: Font | None = None, anchor: str | None = None
|
| 453 |
+
) -> tuple[float, float, float, float]:
|
| 454 |
+
return (font or self.font).getbbox(
|
| 455 |
+
text,
|
| 456 |
+
self._get_fontmode(),
|
| 457 |
+
self.direction,
|
| 458 |
+
self.features,
|
| 459 |
+
self.language,
|
| 460 |
+
self.stroke_width,
|
| 461 |
+
anchor,
|
| 462 |
+
)
|
| 463 |
+
|
| 464 |
+
def get_bbox(
|
| 465 |
+
self,
|
| 466 |
+
xy: tuple[float, float] = (0, 0),
|
| 467 |
+
anchor: str | None = None,
|
| 468 |
+
align: str = "left",
|
| 469 |
+
) -> tuple[float, float, float, float]:
|
| 470 |
+
"""
|
| 471 |
+
Returns bounding box (in pixels) of text.
|
| 472 |
+
|
| 473 |
+
Use :py:meth:`get_length` to get the offset of following text with 1/64 pixel
|
| 474 |
+
precision. The bounding box includes extra margins for some fonts, e.g. italics
|
| 475 |
+
or accents.
|
| 476 |
+
|
| 477 |
+
:param xy: The anchor coordinates of the text.
|
| 478 |
+
:param anchor: The text anchor alignment. Determines the relative location of
|
| 479 |
+
the anchor to the text. The default alignment is top left,
|
| 480 |
+
specifically ``la`` for horizontal text and ``lt`` for
|
| 481 |
+
vertical text. See :ref:`text-anchors` for details.
|
| 482 |
+
:param align: For multiline text, ``"left"``, ``"center"``, ``"right"`` or
|
| 483 |
+
``"justify"`` determines the relative alignment of lines. Use the
|
| 484 |
+
``anchor`` parameter to specify the alignment to ``xy``.
|
| 485 |
+
|
| 486 |
+
:return: ``(left, top, right, bottom)`` bounding box
|
| 487 |
+
"""
|
| 488 |
+
bbox: tuple[float, float, float, float] | None = None
|
| 489 |
+
for x, y, anchor, text in self._split(xy, anchor, align):
|
| 490 |
+
bbox_line = self._get_bbox(text, anchor=anchor)
|
| 491 |
+
bbox_line = (
|
| 492 |
+
bbox_line[0] + x,
|
| 493 |
+
bbox_line[1] + y,
|
| 494 |
+
bbox_line[2] + x,
|
| 495 |
+
bbox_line[3] + y,
|
| 496 |
+
)
|
| 497 |
+
if bbox is None:
|
| 498 |
+
bbox = bbox_line
|
| 499 |
+
else:
|
| 500 |
+
bbox = (
|
| 501 |
+
min(bbox[0], bbox_line[0]),
|
| 502 |
+
min(bbox[1], bbox_line[1]),
|
| 503 |
+
max(bbox[2], bbox_line[2]),
|
| 504 |
+
max(bbox[3], bbox_line[3]),
|
| 505 |
+
)
|
| 506 |
+
|
| 507 |
+
assert bbox is not None
|
| 508 |
+
return bbox
|
.venv/lib/python3.12/site-packages/PIL/ImageTransform.py
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# The Python Imaging Library.
|
| 3 |
+
# $Id$
|
| 4 |
+
#
|
| 5 |
+
# transform wrappers
|
| 6 |
+
#
|
| 7 |
+
# History:
|
| 8 |
+
# 2002-04-08 fl Created
|
| 9 |
+
#
|
| 10 |
+
# Copyright (c) 2002 by Secret Labs AB
|
| 11 |
+
# Copyright (c) 2002 by Fredrik Lundh
|
| 12 |
+
#
|
| 13 |
+
# See the README file for information on usage and redistribution.
|
| 14 |
+
#
|
| 15 |
+
from __future__ import annotations
|
| 16 |
+
|
| 17 |
+
from collections.abc import Sequence
|
| 18 |
+
from typing import Any
|
| 19 |
+
|
| 20 |
+
from . import Image
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
class Transform(Image.ImageTransformHandler):
|
| 24 |
+
"""Base class for other transforms defined in :py:mod:`~PIL.ImageTransform`."""
|
| 25 |
+
|
| 26 |
+
method: Image.Transform
|
| 27 |
+
|
| 28 |
+
def __init__(self, data: Sequence[Any]) -> None:
|
| 29 |
+
self.data = data
|
| 30 |
+
|
| 31 |
+
def getdata(self) -> tuple[Image.Transform, Sequence[int]]:
|
| 32 |
+
return self.method, self.data
|
| 33 |
+
|
| 34 |
+
def transform(
|
| 35 |
+
self,
|
| 36 |
+
size: tuple[int, int],
|
| 37 |
+
image: Image.Image,
|
| 38 |
+
**options: Any,
|
| 39 |
+
) -> Image.Image:
|
| 40 |
+
"""Perform the transform. Called from :py:meth:`.Image.transform`."""
|
| 41 |
+
# can be overridden
|
| 42 |
+
method, data = self.getdata()
|
| 43 |
+
return image.transform(size, method, data, **options)
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
class AffineTransform(Transform):
|
| 47 |
+
"""
|
| 48 |
+
Define an affine image transform.
|
| 49 |
+
|
| 50 |
+
This function takes a 6-tuple (a, b, c, d, e, f) which contain the first
|
| 51 |
+
two rows from the inverse of an affine transform matrix. For each pixel
|
| 52 |
+
(x, y) in the output image, the new value is taken from a position (a x +
|
| 53 |
+
b y + c, d x + e y + f) in the input image, rounded to nearest pixel.
|
| 54 |
+
|
| 55 |
+
This function can be used to scale, translate, rotate, and shear the
|
| 56 |
+
original image.
|
| 57 |
+
|
| 58 |
+
See :py:meth:`.Image.transform`
|
| 59 |
+
|
| 60 |
+
:param matrix: A 6-tuple (a, b, c, d, e, f) containing the first two rows
|
| 61 |
+
from the inverse of an affine transform matrix.
|
| 62 |
+
"""
|
| 63 |
+
|
| 64 |
+
method = Image.Transform.AFFINE
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
class PerspectiveTransform(Transform):
|
| 68 |
+
"""
|
| 69 |
+
Define a perspective image transform.
|
| 70 |
+
|
| 71 |
+
This function takes an 8-tuple (a, b, c, d, e, f, g, h). For each pixel
|
| 72 |
+
(x, y) in the output image, the new value is taken from a position
|
| 73 |
+
((a x + b y + c) / (g x + h y + 1), (d x + e y + f) / (g x + h y + 1)) in
|
| 74 |
+
the input image, rounded to nearest pixel.
|
| 75 |
+
|
| 76 |
+
This function can be used to scale, translate, rotate, and shear the
|
| 77 |
+
original image.
|
| 78 |
+
|
| 79 |
+
See :py:meth:`.Image.transform`
|
| 80 |
+
|
| 81 |
+
:param matrix: An 8-tuple (a, b, c, d, e, f, g, h).
|
| 82 |
+
"""
|
| 83 |
+
|
| 84 |
+
method = Image.Transform.PERSPECTIVE
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
class ExtentTransform(Transform):
|
| 88 |
+
"""
|
| 89 |
+
Define a transform to extract a subregion from an image.
|
| 90 |
+
|
| 91 |
+
Maps a rectangle (defined by two corners) from the image to a rectangle of
|
| 92 |
+
the given size. The resulting image will contain data sampled from between
|
| 93 |
+
the corners, such that (x0, y0) in the input image will end up at (0,0) in
|
| 94 |
+
the output image, and (x1, y1) at size.
|
| 95 |
+
|
| 96 |
+
This method can be used to crop, stretch, shrink, or mirror an arbitrary
|
| 97 |
+
rectangle in the current image. It is slightly slower than crop, but about
|
| 98 |
+
as fast as a corresponding resize operation.
|
| 99 |
+
|
| 100 |
+
See :py:meth:`.Image.transform`
|
| 101 |
+
|
| 102 |
+
:param bbox: A 4-tuple (x0, y0, x1, y1) which specifies two points in the
|
| 103 |
+
input image's coordinate system. See :ref:`coordinate-system`.
|
| 104 |
+
"""
|
| 105 |
+
|
| 106 |
+
method = Image.Transform.EXTENT
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
class QuadTransform(Transform):
|
| 110 |
+
"""
|
| 111 |
+
Define a quad image transform.
|
| 112 |
+
|
| 113 |
+
Maps a quadrilateral (a region defined by four corners) from the image to a
|
| 114 |
+
rectangle of the given size.
|
| 115 |
+
|
| 116 |
+
See :py:meth:`.Image.transform`
|
| 117 |
+
|
| 118 |
+
:param xy: An 8-tuple (x0, y0, x1, y1, x2, y2, x3, y3) which contain the
|
| 119 |
+
upper left, lower left, lower right, and upper right corner of the
|
| 120 |
+
source quadrilateral.
|
| 121 |
+
"""
|
| 122 |
+
|
| 123 |
+
method = Image.Transform.QUAD
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
class MeshTransform(Transform):
|
| 127 |
+
"""
|
| 128 |
+
Define a mesh image transform. A mesh transform consists of one or more
|
| 129 |
+
individual quad transforms.
|
| 130 |
+
|
| 131 |
+
See :py:meth:`.Image.transform`
|
| 132 |
+
|
| 133 |
+
:param data: A list of (bbox, quad) tuples.
|
| 134 |
+
"""
|
| 135 |
+
|
| 136 |
+
method = Image.Transform.MESH
|
.venv/lib/python3.12/site-packages/PIL/ImtImagePlugin.py
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# The Python Imaging Library.
|
| 3 |
+
# $Id$
|
| 4 |
+
#
|
| 5 |
+
# IM Tools support for PIL
|
| 6 |
+
#
|
| 7 |
+
# history:
|
| 8 |
+
# 1996-05-27 fl Created (read 8-bit images only)
|
| 9 |
+
# 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.2)
|
| 10 |
+
#
|
| 11 |
+
# Copyright (c) Secret Labs AB 1997-2001.
|
| 12 |
+
# Copyright (c) Fredrik Lundh 1996-2001.
|
| 13 |
+
#
|
| 14 |
+
# See the README file for information on usage and redistribution.
|
| 15 |
+
#
|
| 16 |
+
from __future__ import annotations
|
| 17 |
+
|
| 18 |
+
import re
|
| 19 |
+
|
| 20 |
+
from . import Image, ImageFile
|
| 21 |
+
|
| 22 |
+
#
|
| 23 |
+
# --------------------------------------------------------------------
|
| 24 |
+
|
| 25 |
+
field = re.compile(rb"([a-z]*) ([^ \r\n]*)")
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
##
|
| 29 |
+
# Image plugin for IM Tools images.
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
class ImtImageFile(ImageFile.ImageFile):
|
| 33 |
+
format = "IMT"
|
| 34 |
+
format_description = "IM Tools"
|
| 35 |
+
|
| 36 |
+
def _open(self) -> None:
|
| 37 |
+
# Quick rejection: if there's not a LF among the first
|
| 38 |
+
# 100 bytes, this is (probably) not a text header.
|
| 39 |
+
|
| 40 |
+
assert self.fp is not None
|
| 41 |
+
|
| 42 |
+
buffer = self.fp.read(100)
|
| 43 |
+
if b"\n" not in buffer:
|
| 44 |
+
msg = "not an IM file"
|
| 45 |
+
raise SyntaxError(msg)
|
| 46 |
+
|
| 47 |
+
xsize = ysize = 0
|
| 48 |
+
|
| 49 |
+
while True:
|
| 50 |
+
if buffer:
|
| 51 |
+
s = buffer[:1]
|
| 52 |
+
buffer = buffer[1:]
|
| 53 |
+
else:
|
| 54 |
+
s = self.fp.read(1)
|
| 55 |
+
if not s:
|
| 56 |
+
break
|
| 57 |
+
|
| 58 |
+
if s == b"\x0c":
|
| 59 |
+
# image data begins
|
| 60 |
+
self.tile = [
|
| 61 |
+
ImageFile._Tile(
|
| 62 |
+
"raw",
|
| 63 |
+
(0, 0) + self.size,
|
| 64 |
+
self.fp.tell() - len(buffer),
|
| 65 |
+
self.mode,
|
| 66 |
+
)
|
| 67 |
+
]
|
| 68 |
+
|
| 69 |
+
break
|
| 70 |
+
|
| 71 |
+
else:
|
| 72 |
+
# read key/value pair
|
| 73 |
+
if b"\n" not in buffer:
|
| 74 |
+
buffer += self.fp.read(100)
|
| 75 |
+
lines = buffer.split(b"\n")
|
| 76 |
+
s += lines.pop(0)
|
| 77 |
+
buffer = b"\n".join(lines)
|
| 78 |
+
if len(s) == 1 or len(s) > 100:
|
| 79 |
+
break
|
| 80 |
+
if s[0] == ord(b"*"):
|
| 81 |
+
continue # comment
|
| 82 |
+
|
| 83 |
+
m = field.match(s)
|
| 84 |
+
if not m:
|
| 85 |
+
break
|
| 86 |
+
k, v = m.group(1, 2)
|
| 87 |
+
if k == b"width":
|
| 88 |
+
xsize = int(v)
|
| 89 |
+
self._size = xsize, ysize
|
| 90 |
+
elif k == b"height":
|
| 91 |
+
ysize = int(v)
|
| 92 |
+
self._size = xsize, ysize
|
| 93 |
+
elif k == b"pixel" and v == b"n8":
|
| 94 |
+
self._mode = "L"
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
#
|
| 98 |
+
# --------------------------------------------------------------------
|
| 99 |
+
|
| 100 |
+
Image.register_open(ImtImageFile.format, ImtImageFile)
|
| 101 |
+
|
| 102 |
+
#
|
| 103 |
+
# no extension registered (".im" is simply too common)
|
.venv/lib/python3.12/site-packages/PIL/PsdImagePlugin.py
ADDED
|
@@ -0,0 +1,337 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# The Python Imaging Library
|
| 3 |
+
# $Id$
|
| 4 |
+
#
|
| 5 |
+
# Adobe PSD 2.5/3.0 file handling
|
| 6 |
+
#
|
| 7 |
+
# History:
|
| 8 |
+
# 1995-09-01 fl Created
|
| 9 |
+
# 1997-01-03 fl Read most PSD images
|
| 10 |
+
# 1997-01-18 fl Fixed P and CMYK support
|
| 11 |
+
# 2001-10-21 fl Added seek/tell support (for layers)
|
| 12 |
+
#
|
| 13 |
+
# Copyright (c) 1997-2001 by Secret Labs AB.
|
| 14 |
+
# Copyright (c) 1995-2001 by Fredrik Lundh
|
| 15 |
+
#
|
| 16 |
+
# See the README file for information on usage and redistribution.
|
| 17 |
+
#
|
| 18 |
+
from __future__ import annotations
|
| 19 |
+
|
| 20 |
+
import io
|
| 21 |
+
from functools import cached_property
|
| 22 |
+
from typing import IO
|
| 23 |
+
|
| 24 |
+
from . import Image, ImageFile, ImagePalette
|
| 25 |
+
from ._binary import i8
|
| 26 |
+
from ._binary import i16be as i16
|
| 27 |
+
from ._binary import i32be as i32
|
| 28 |
+
from ._binary import si16be as si16
|
| 29 |
+
from ._binary import si32be as si32
|
| 30 |
+
from ._util import DeferredError
|
| 31 |
+
|
| 32 |
+
MODES = {
|
| 33 |
+
# (photoshop mode, bits) -> (pil mode, required channels)
|
| 34 |
+
(0, 1): ("1", 1),
|
| 35 |
+
(0, 8): ("L", 1),
|
| 36 |
+
(1, 8): ("L", 1),
|
| 37 |
+
(2, 8): ("P", 1),
|
| 38 |
+
(3, 8): ("RGB", 3),
|
| 39 |
+
(4, 8): ("CMYK", 4),
|
| 40 |
+
(7, 8): ("L", 1), # FIXME: multilayer
|
| 41 |
+
(8, 8): ("L", 1), # duotone
|
| 42 |
+
(9, 8): ("LAB", 3),
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
# --------------------------------------------------------------------.
|
| 47 |
+
# read PSD images
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
def _accept(prefix: bytes) -> bool:
|
| 51 |
+
return prefix.startswith(b"8BPS")
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
##
|
| 55 |
+
# Image plugin for Photoshop images.
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
class PsdImageFile(ImageFile.ImageFile):
|
| 59 |
+
format = "PSD"
|
| 60 |
+
format_description = "Adobe Photoshop"
|
| 61 |
+
_close_exclusive_fp_after_loading = False
|
| 62 |
+
|
| 63 |
+
def _open(self) -> None:
|
| 64 |
+
assert self.fp is not None
|
| 65 |
+
read = self.fp.read
|
| 66 |
+
|
| 67 |
+
#
|
| 68 |
+
# header
|
| 69 |
+
|
| 70 |
+
s = read(26)
|
| 71 |
+
if not _accept(s) or i16(s, 4) != 1:
|
| 72 |
+
msg = "not a PSD file"
|
| 73 |
+
raise SyntaxError(msg)
|
| 74 |
+
|
| 75 |
+
psd_bits = i16(s, 22)
|
| 76 |
+
psd_channels = i16(s, 12)
|
| 77 |
+
psd_mode = i16(s, 24)
|
| 78 |
+
|
| 79 |
+
mode, channels = MODES[(psd_mode, psd_bits)]
|
| 80 |
+
|
| 81 |
+
if channels > psd_channels:
|
| 82 |
+
msg = "not enough channels"
|
| 83 |
+
raise OSError(msg)
|
| 84 |
+
if mode == "RGB" and psd_channels == 4:
|
| 85 |
+
mode = "RGBA"
|
| 86 |
+
channels = 4
|
| 87 |
+
|
| 88 |
+
self._mode = mode
|
| 89 |
+
self._size = i32(s, 18), i32(s, 14)
|
| 90 |
+
|
| 91 |
+
#
|
| 92 |
+
# color mode data
|
| 93 |
+
|
| 94 |
+
size = i32(read(4))
|
| 95 |
+
if size:
|
| 96 |
+
data = read(size)
|
| 97 |
+
if mode == "P" and size == 768:
|
| 98 |
+
self.palette = ImagePalette.raw("RGB;L", data)
|
| 99 |
+
|
| 100 |
+
#
|
| 101 |
+
# image resources
|
| 102 |
+
|
| 103 |
+
self.resources = []
|
| 104 |
+
|
| 105 |
+
size = i32(read(4))
|
| 106 |
+
if size:
|
| 107 |
+
# load resources
|
| 108 |
+
end = self.fp.tell() + size
|
| 109 |
+
while self.fp.tell() < end:
|
| 110 |
+
read(4) # signature
|
| 111 |
+
id = i16(read(2))
|
| 112 |
+
name = read(i8(read(1)))
|
| 113 |
+
if not (len(name) & 1):
|
| 114 |
+
read(1) # padding
|
| 115 |
+
data = read(i32(read(4)))
|
| 116 |
+
if len(data) & 1:
|
| 117 |
+
read(1) # padding
|
| 118 |
+
self.resources.append((id, name, data))
|
| 119 |
+
if id == 1039: # ICC profile
|
| 120 |
+
self.info["icc_profile"] = data
|
| 121 |
+
|
| 122 |
+
#
|
| 123 |
+
# layer and mask information
|
| 124 |
+
|
| 125 |
+
self._layers_position = None
|
| 126 |
+
|
| 127 |
+
size = i32(read(4))
|
| 128 |
+
if size:
|
| 129 |
+
end = self.fp.tell() + size
|
| 130 |
+
size = i32(read(4))
|
| 131 |
+
if size:
|
| 132 |
+
self._layers_position = self.fp.tell()
|
| 133 |
+
self._layers_size = size
|
| 134 |
+
self.fp.seek(end)
|
| 135 |
+
self._n_frames: int | None = None
|
| 136 |
+
|
| 137 |
+
#
|
| 138 |
+
# image descriptor
|
| 139 |
+
|
| 140 |
+
self.tile = _maketile(self.fp, mode, (0, 0) + self.size, channels)
|
| 141 |
+
|
| 142 |
+
# keep the file open
|
| 143 |
+
self._fp = self.fp
|
| 144 |
+
self.frame = 1
|
| 145 |
+
self._min_frame = 1
|
| 146 |
+
|
| 147 |
+
@cached_property
|
| 148 |
+
def layers(
|
| 149 |
+
self,
|
| 150 |
+
) -> list[tuple[str, str, tuple[int, int, int, int], list[ImageFile._Tile]]]:
|
| 151 |
+
layers = []
|
| 152 |
+
if self._layers_position is not None:
|
| 153 |
+
if isinstance(self._fp, DeferredError):
|
| 154 |
+
raise self._fp.ex
|
| 155 |
+
self._fp.seek(self._layers_position)
|
| 156 |
+
_layer_data = io.BytesIO(ImageFile._safe_read(self._fp, self._layers_size))
|
| 157 |
+
layers = _layerinfo(_layer_data, self._layers_size)
|
| 158 |
+
self._n_frames = len(layers)
|
| 159 |
+
return layers
|
| 160 |
+
|
| 161 |
+
@property
|
| 162 |
+
def n_frames(self) -> int:
|
| 163 |
+
if self._n_frames is None:
|
| 164 |
+
self._n_frames = len(self.layers)
|
| 165 |
+
return self._n_frames
|
| 166 |
+
|
| 167 |
+
@property
|
| 168 |
+
def is_animated(self) -> bool:
|
| 169 |
+
return len(self.layers) > 1
|
| 170 |
+
|
| 171 |
+
def seek(self, layer: int) -> None:
|
| 172 |
+
if not self._seek_check(layer):
|
| 173 |
+
return
|
| 174 |
+
if isinstance(self._fp, DeferredError):
|
| 175 |
+
raise self._fp.ex
|
| 176 |
+
|
| 177 |
+
# seek to given layer (1..max)
|
| 178 |
+
if layer > len(self.layers):
|
| 179 |
+
msg = "no more images in PSD file"
|
| 180 |
+
raise EOFError(msg)
|
| 181 |
+
_, mode, _, tile = self.layers[layer - 1]
|
| 182 |
+
self._mode = mode
|
| 183 |
+
self.tile = tile
|
| 184 |
+
self.frame = layer
|
| 185 |
+
self.fp = self._fp
|
| 186 |
+
|
| 187 |
+
def tell(self) -> int:
|
| 188 |
+
# return layer number (0=image, 1..max=layers)
|
| 189 |
+
return self.frame
|
| 190 |
+
|
| 191 |
+
|
| 192 |
+
def _layerinfo(
|
| 193 |
+
fp: IO[bytes], ct_bytes: int
|
| 194 |
+
) -> list[tuple[str, str, tuple[int, int, int, int], list[ImageFile._Tile]]]:
|
| 195 |
+
# read layerinfo block
|
| 196 |
+
layers = []
|
| 197 |
+
|
| 198 |
+
def read(size: int) -> bytes:
|
| 199 |
+
return ImageFile._safe_read(fp, size)
|
| 200 |
+
|
| 201 |
+
ct = si16(read(2))
|
| 202 |
+
|
| 203 |
+
# sanity check
|
| 204 |
+
if ct_bytes < (abs(ct) * 20):
|
| 205 |
+
msg = "Layer block too short for number of layers requested"
|
| 206 |
+
raise SyntaxError(msg)
|
| 207 |
+
|
| 208 |
+
for _ in range(abs(ct)):
|
| 209 |
+
# bounding box
|
| 210 |
+
y0 = si32(read(4))
|
| 211 |
+
x0 = si32(read(4))
|
| 212 |
+
y1 = si32(read(4))
|
| 213 |
+
x1 = si32(read(4))
|
| 214 |
+
|
| 215 |
+
# image info
|
| 216 |
+
bands = []
|
| 217 |
+
ct_types = i16(read(2))
|
| 218 |
+
if ct_types > 4:
|
| 219 |
+
fp.seek(ct_types * 6 + 12, io.SEEK_CUR)
|
| 220 |
+
size = i32(read(4))
|
| 221 |
+
fp.seek(size, io.SEEK_CUR)
|
| 222 |
+
continue
|
| 223 |
+
|
| 224 |
+
for _ in range(ct_types):
|
| 225 |
+
type = i16(read(2))
|
| 226 |
+
|
| 227 |
+
if type == 65535:
|
| 228 |
+
b = "A"
|
| 229 |
+
else:
|
| 230 |
+
b = "RGBA"[type]
|
| 231 |
+
|
| 232 |
+
bands.append(b)
|
| 233 |
+
read(4) # size
|
| 234 |
+
|
| 235 |
+
# figure out the image mode
|
| 236 |
+
bands.sort()
|
| 237 |
+
if bands == ["R"]:
|
| 238 |
+
mode = "L"
|
| 239 |
+
elif bands == ["B", "G", "R"]:
|
| 240 |
+
mode = "RGB"
|
| 241 |
+
elif bands == ["A", "B", "G", "R"]:
|
| 242 |
+
mode = "RGBA"
|
| 243 |
+
else:
|
| 244 |
+
mode = "" # unknown
|
| 245 |
+
|
| 246 |
+
# skip over blend flags and extra information
|
| 247 |
+
read(12) # filler
|
| 248 |
+
name = ""
|
| 249 |
+
size = i32(read(4)) # length of the extra data field
|
| 250 |
+
if size:
|
| 251 |
+
data_end = fp.tell() + size
|
| 252 |
+
|
| 253 |
+
length = i32(read(4))
|
| 254 |
+
if length:
|
| 255 |
+
fp.seek(length - 16, io.SEEK_CUR)
|
| 256 |
+
|
| 257 |
+
length = i32(read(4))
|
| 258 |
+
if length:
|
| 259 |
+
fp.seek(length, io.SEEK_CUR)
|
| 260 |
+
|
| 261 |
+
length = i8(read(1))
|
| 262 |
+
if length:
|
| 263 |
+
# Don't know the proper encoding,
|
| 264 |
+
# Latin-1 should be a good guess
|
| 265 |
+
name = read(length).decode("latin-1", "replace")
|
| 266 |
+
|
| 267 |
+
fp.seek(data_end)
|
| 268 |
+
layers.append((name, mode, (x0, y0, x1, y1)))
|
| 269 |
+
|
| 270 |
+
# get tiles
|
| 271 |
+
layerinfo = []
|
| 272 |
+
for i, (name, mode, bbox) in enumerate(layers):
|
| 273 |
+
tile = []
|
| 274 |
+
for m in mode:
|
| 275 |
+
t = _maketile(fp, m, bbox, 1)
|
| 276 |
+
if t:
|
| 277 |
+
tile.extend(t)
|
| 278 |
+
layerinfo.append((name, mode, bbox, tile))
|
| 279 |
+
|
| 280 |
+
return layerinfo
|
| 281 |
+
|
| 282 |
+
|
| 283 |
+
def _maketile(
|
| 284 |
+
file: IO[bytes], mode: str, bbox: tuple[int, int, int, int], channels: int
|
| 285 |
+
) -> list[ImageFile._Tile]:
|
| 286 |
+
tiles = []
|
| 287 |
+
read = file.read
|
| 288 |
+
|
| 289 |
+
compression = i16(read(2))
|
| 290 |
+
|
| 291 |
+
xsize = bbox[2] - bbox[0]
|
| 292 |
+
ysize = bbox[3] - bbox[1]
|
| 293 |
+
|
| 294 |
+
offset = file.tell()
|
| 295 |
+
|
| 296 |
+
if compression == 0:
|
| 297 |
+
#
|
| 298 |
+
# raw compression
|
| 299 |
+
for channel in range(channels):
|
| 300 |
+
layer = mode[channel]
|
| 301 |
+
if mode == "CMYK":
|
| 302 |
+
layer += ";I"
|
| 303 |
+
tiles.append(ImageFile._Tile("raw", bbox, offset, layer))
|
| 304 |
+
offset = offset + xsize * ysize
|
| 305 |
+
|
| 306 |
+
elif compression == 1:
|
| 307 |
+
#
|
| 308 |
+
# packbits compression
|
| 309 |
+
i = 0
|
| 310 |
+
bytecount = read(channels * ysize * 2)
|
| 311 |
+
offset = file.tell()
|
| 312 |
+
for channel in range(channels):
|
| 313 |
+
layer = mode[channel]
|
| 314 |
+
if mode == "CMYK":
|
| 315 |
+
layer += ";I"
|
| 316 |
+
tiles.append(ImageFile._Tile("packbits", bbox, offset, layer))
|
| 317 |
+
for y in range(ysize):
|
| 318 |
+
offset = offset + i16(bytecount, i)
|
| 319 |
+
i += 2
|
| 320 |
+
|
| 321 |
+
file.seek(offset)
|
| 322 |
+
|
| 323 |
+
if offset & 1:
|
| 324 |
+
read(1) # padding
|
| 325 |
+
|
| 326 |
+
return tiles
|
| 327 |
+
|
| 328 |
+
|
| 329 |
+
# --------------------------------------------------------------------
|
| 330 |
+
# registry
|
| 331 |
+
|
| 332 |
+
|
| 333 |
+
Image.register_open(PsdImageFile.format, PsdImageFile, _accept)
|
| 334 |
+
|
| 335 |
+
Image.register_extension(PsdImageFile.format, ".psd")
|
| 336 |
+
|
| 337 |
+
Image.register_mime(PsdImageFile.format, "image/vnd.adobe.photoshop")
|
.venv/lib/python3.12/site-packages/PIL/QoiImagePlugin.py
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# The Python Imaging Library.
|
| 3 |
+
#
|
| 4 |
+
# QOI support for PIL
|
| 5 |
+
#
|
| 6 |
+
# See the README file for information on usage and redistribution.
|
| 7 |
+
#
|
| 8 |
+
from __future__ import annotations
|
| 9 |
+
|
| 10 |
+
import os
|
| 11 |
+
from typing import IO
|
| 12 |
+
|
| 13 |
+
from . import Image, ImageFile
|
| 14 |
+
from ._binary import i32be as i32
|
| 15 |
+
from ._binary import o8
|
| 16 |
+
from ._binary import o32be as o32
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def _accept(prefix: bytes) -> bool:
|
| 20 |
+
return prefix.startswith(b"qoif")
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
class QoiImageFile(ImageFile.ImageFile):
|
| 24 |
+
format = "QOI"
|
| 25 |
+
format_description = "Quite OK Image"
|
| 26 |
+
|
| 27 |
+
def _open(self) -> None:
|
| 28 |
+
assert self.fp is not None
|
| 29 |
+
if not _accept(self.fp.read(4)):
|
| 30 |
+
msg = "not a QOI file"
|
| 31 |
+
raise SyntaxError(msg)
|
| 32 |
+
|
| 33 |
+
self._size = i32(self.fp.read(4)), i32(self.fp.read(4))
|
| 34 |
+
|
| 35 |
+
channels = self.fp.read(1)[0]
|
| 36 |
+
self._mode = "RGB" if channels == 3 else "RGBA"
|
| 37 |
+
|
| 38 |
+
self.fp.seek(1, os.SEEK_CUR) # colorspace
|
| 39 |
+
self.tile = [ImageFile._Tile("qoi", (0, 0) + self._size, self.fp.tell())]
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
class QoiDecoder(ImageFile.PyDecoder):
|
| 43 |
+
_pulls_fd = True
|
| 44 |
+
_previous_pixel: bytes | bytearray | None = None
|
| 45 |
+
_previously_seen_pixels: dict[int, bytes | bytearray] = {}
|
| 46 |
+
|
| 47 |
+
def _add_to_previous_pixels(self, value: bytes | bytearray) -> None:
|
| 48 |
+
self._previous_pixel = value
|
| 49 |
+
|
| 50 |
+
r, g, b, a = value
|
| 51 |
+
hash_value = (r * 3 + g * 5 + b * 7 + a * 11) % 64
|
| 52 |
+
self._previously_seen_pixels[hash_value] = value
|
| 53 |
+
|
| 54 |
+
def decode(self, buffer: bytes | Image.SupportsArrayInterface) -> tuple[int, int]:
|
| 55 |
+
assert self.fd is not None
|
| 56 |
+
|
| 57 |
+
self._previously_seen_pixels = {}
|
| 58 |
+
self._previous_pixel = bytearray((0, 0, 0, 255))
|
| 59 |
+
|
| 60 |
+
data = bytearray()
|
| 61 |
+
bands = Image.getmodebands(self.mode)
|
| 62 |
+
dest_length = self.state.xsize * self.state.ysize * bands
|
| 63 |
+
while len(data) < dest_length:
|
| 64 |
+
byte = self.fd.read(1)[0]
|
| 65 |
+
value: bytes | bytearray
|
| 66 |
+
if byte == 0b11111110 and self._previous_pixel: # QOI_OP_RGB
|
| 67 |
+
value = bytearray(self.fd.read(3)) + self._previous_pixel[3:]
|
| 68 |
+
elif byte == 0b11111111: # QOI_OP_RGBA
|
| 69 |
+
value = self.fd.read(4)
|
| 70 |
+
else:
|
| 71 |
+
op = byte >> 6
|
| 72 |
+
if op == 0: # QOI_OP_INDEX
|
| 73 |
+
op_index = byte & 0b00111111
|
| 74 |
+
value = self._previously_seen_pixels.get(
|
| 75 |
+
op_index, bytearray((0, 0, 0, 0))
|
| 76 |
+
)
|
| 77 |
+
elif op == 1 and self._previous_pixel: # QOI_OP_DIFF
|
| 78 |
+
value = bytearray(
|
| 79 |
+
(
|
| 80 |
+
(self._previous_pixel[0] + ((byte & 0b00110000) >> 4) - 2)
|
| 81 |
+
% 256,
|
| 82 |
+
(self._previous_pixel[1] + ((byte & 0b00001100) >> 2) - 2)
|
| 83 |
+
% 256,
|
| 84 |
+
(self._previous_pixel[2] + (byte & 0b00000011) - 2) % 256,
|
| 85 |
+
self._previous_pixel[3],
|
| 86 |
+
)
|
| 87 |
+
)
|
| 88 |
+
elif op == 2 and self._previous_pixel: # QOI_OP_LUMA
|
| 89 |
+
second_byte = self.fd.read(1)[0]
|
| 90 |
+
diff_green = (byte & 0b00111111) - 32
|
| 91 |
+
diff_red = ((second_byte & 0b11110000) >> 4) - 8
|
| 92 |
+
diff_blue = (second_byte & 0b00001111) - 8
|
| 93 |
+
|
| 94 |
+
value = bytearray(
|
| 95 |
+
tuple(
|
| 96 |
+
(self._previous_pixel[i] + diff_green + diff) % 256
|
| 97 |
+
for i, diff in enumerate((diff_red, 0, diff_blue))
|
| 98 |
+
)
|
| 99 |
+
)
|
| 100 |
+
value += self._previous_pixel[3:]
|
| 101 |
+
elif op == 3 and self._previous_pixel: # QOI_OP_RUN
|
| 102 |
+
run_length = (byte & 0b00111111) + 1
|
| 103 |
+
value = self._previous_pixel
|
| 104 |
+
if bands == 3:
|
| 105 |
+
value = value[:3]
|
| 106 |
+
data += value * run_length
|
| 107 |
+
continue
|
| 108 |
+
self._add_to_previous_pixels(value)
|
| 109 |
+
|
| 110 |
+
if bands == 3:
|
| 111 |
+
value = value[:3]
|
| 112 |
+
data += value
|
| 113 |
+
self.set_as_raw(data)
|
| 114 |
+
return -1, 0
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
|
| 118 |
+
if im.mode == "RGB":
|
| 119 |
+
channels = 3
|
| 120 |
+
elif im.mode == "RGBA":
|
| 121 |
+
channels = 4
|
| 122 |
+
else:
|
| 123 |
+
msg = "Unsupported QOI image mode"
|
| 124 |
+
raise ValueError(msg)
|
| 125 |
+
|
| 126 |
+
colorspace = 0 if im.encoderinfo.get("colorspace") == "sRGB" else 1
|
| 127 |
+
|
| 128 |
+
fp.write(b"qoif")
|
| 129 |
+
fp.write(o32(im.size[0]))
|
| 130 |
+
fp.write(o32(im.size[1]))
|
| 131 |
+
fp.write(o8(channels))
|
| 132 |
+
fp.write(o8(colorspace))
|
| 133 |
+
|
| 134 |
+
ImageFile._save(im, fp, [ImageFile._Tile("qoi", (0, 0) + im.size)])
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
class QoiEncoder(ImageFile.PyEncoder):
|
| 138 |
+
_pushes_fd = True
|
| 139 |
+
_previous_pixel: tuple[int, int, int, int] | None = None
|
| 140 |
+
_previously_seen_pixels: dict[int, tuple[int, int, int, int]] = {}
|
| 141 |
+
_run = 0
|
| 142 |
+
|
| 143 |
+
def _write_run(self) -> bytes:
|
| 144 |
+
data = o8(0b11000000 | (self._run - 1)) # QOI_OP_RUN
|
| 145 |
+
self._run = 0
|
| 146 |
+
return data
|
| 147 |
+
|
| 148 |
+
def _delta(self, left: int, right: int) -> int:
|
| 149 |
+
result = (left - right) & 255
|
| 150 |
+
if result >= 128:
|
| 151 |
+
result -= 256
|
| 152 |
+
return result
|
| 153 |
+
|
| 154 |
+
def encode(self, bufsize: int) -> tuple[int, int, bytes]:
|
| 155 |
+
assert self.im is not None
|
| 156 |
+
|
| 157 |
+
self._previously_seen_pixels = {0: (0, 0, 0, 0)}
|
| 158 |
+
self._previous_pixel = (0, 0, 0, 255)
|
| 159 |
+
|
| 160 |
+
data = bytearray()
|
| 161 |
+
w, h = self.im.size
|
| 162 |
+
bands = Image.getmodebands(self.mode)
|
| 163 |
+
|
| 164 |
+
for y in range(h):
|
| 165 |
+
for x in range(w):
|
| 166 |
+
pixel = self.im.getpixel((x, y))
|
| 167 |
+
if bands == 3:
|
| 168 |
+
pixel = (*pixel, 255)
|
| 169 |
+
|
| 170 |
+
if pixel == self._previous_pixel:
|
| 171 |
+
self._run += 1
|
| 172 |
+
if self._run == 62:
|
| 173 |
+
data += self._write_run()
|
| 174 |
+
else:
|
| 175 |
+
if self._run:
|
| 176 |
+
data += self._write_run()
|
| 177 |
+
|
| 178 |
+
r, g, b, a = pixel
|
| 179 |
+
hash_value = (r * 3 + g * 5 + b * 7 + a * 11) % 64
|
| 180 |
+
if self._previously_seen_pixels.get(hash_value) == pixel:
|
| 181 |
+
data += o8(hash_value) # QOI_OP_INDEX
|
| 182 |
+
elif self._previous_pixel:
|
| 183 |
+
self._previously_seen_pixels[hash_value] = pixel
|
| 184 |
+
|
| 185 |
+
prev_r, prev_g, prev_b, prev_a = self._previous_pixel
|
| 186 |
+
if prev_a == a:
|
| 187 |
+
delta_r = self._delta(r, prev_r)
|
| 188 |
+
delta_g = self._delta(g, prev_g)
|
| 189 |
+
delta_b = self._delta(b, prev_b)
|
| 190 |
+
|
| 191 |
+
if (
|
| 192 |
+
-2 <= delta_r < 2
|
| 193 |
+
and -2 <= delta_g < 2
|
| 194 |
+
and -2 <= delta_b < 2
|
| 195 |
+
):
|
| 196 |
+
data += o8(
|
| 197 |
+
0b01000000
|
| 198 |
+
| (delta_r + 2) << 4
|
| 199 |
+
| (delta_g + 2) << 2
|
| 200 |
+
| (delta_b + 2)
|
| 201 |
+
) # QOI_OP_DIFF
|
| 202 |
+
else:
|
| 203 |
+
delta_gr = self._delta(delta_r, delta_g)
|
| 204 |
+
delta_gb = self._delta(delta_b, delta_g)
|
| 205 |
+
if (
|
| 206 |
+
-8 <= delta_gr < 8
|
| 207 |
+
and -32 <= delta_g < 32
|
| 208 |
+
and -8 <= delta_gb < 8
|
| 209 |
+
):
|
| 210 |
+
data += o8(
|
| 211 |
+
0b10000000 | (delta_g + 32)
|
| 212 |
+
) # QOI_OP_LUMA
|
| 213 |
+
data += o8((delta_gr + 8) << 4 | (delta_gb + 8))
|
| 214 |
+
else:
|
| 215 |
+
data += o8(0b11111110) # QOI_OP_RGB
|
| 216 |
+
data += bytes(pixel[:3])
|
| 217 |
+
else:
|
| 218 |
+
data += o8(0b11111111) # QOI_OP_RGBA
|
| 219 |
+
data += bytes(pixel)
|
| 220 |
+
|
| 221 |
+
self._previous_pixel = pixel
|
| 222 |
+
|
| 223 |
+
if self._run:
|
| 224 |
+
data += self._write_run()
|
| 225 |
+
data += bytes((0, 0, 0, 0, 0, 0, 0, 1)) # padding
|
| 226 |
+
|
| 227 |
+
return len(data), 0, data
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
Image.register_open(QoiImageFile.format, QoiImageFile, _accept)
|
| 231 |
+
Image.register_decoder("qoi", QoiDecoder)
|
| 232 |
+
Image.register_extension(QoiImageFile.format, ".qoi")
|
| 233 |
+
|
| 234 |
+
Image.register_save(QoiImageFile.format, _save)
|
| 235 |
+
Image.register_encoder("qoi", QoiEncoder)
|
.venv/lib/python3.12/site-packages/PIL/WmfImagePlugin.py
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# The Python Imaging Library
|
| 3 |
+
# $Id$
|
| 4 |
+
#
|
| 5 |
+
# WMF stub codec
|
| 6 |
+
#
|
| 7 |
+
# history:
|
| 8 |
+
# 1996-12-14 fl Created
|
| 9 |
+
# 2004-02-22 fl Turned into a stub driver
|
| 10 |
+
# 2004-02-23 fl Added EMF support
|
| 11 |
+
#
|
| 12 |
+
# Copyright (c) Secret Labs AB 1997-2004. All rights reserved.
|
| 13 |
+
# Copyright (c) Fredrik Lundh 1996.
|
| 14 |
+
#
|
| 15 |
+
# See the README file for information on usage and redistribution.
|
| 16 |
+
#
|
| 17 |
+
# WMF/EMF reference documentation:
|
| 18 |
+
# https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-WMF/[MS-WMF].pdf
|
| 19 |
+
# http://wvware.sourceforge.net/caolan/index.html
|
| 20 |
+
# http://wvware.sourceforge.net/caolan/ora-wmf.html
|
| 21 |
+
from __future__ import annotations
|
| 22 |
+
|
| 23 |
+
from typing import IO
|
| 24 |
+
|
| 25 |
+
from . import Image, ImageFile
|
| 26 |
+
from ._binary import i16le as word
|
| 27 |
+
from ._binary import si16le as short
|
| 28 |
+
from ._binary import si32le as _long
|
| 29 |
+
|
| 30 |
+
_handler = None
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def register_handler(handler: ImageFile.StubHandler | None) -> None:
|
| 34 |
+
"""
|
| 35 |
+
Install application-specific WMF image handler.
|
| 36 |
+
|
| 37 |
+
:param handler: Handler object.
|
| 38 |
+
"""
|
| 39 |
+
global _handler
|
| 40 |
+
_handler = handler
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
if hasattr(Image.core, "drawwmf"):
|
| 44 |
+
# install default handler (windows only)
|
| 45 |
+
|
| 46 |
+
class WmfHandler(ImageFile.StubHandler):
|
| 47 |
+
def open(self, im: ImageFile.StubImageFile) -> None:
|
| 48 |
+
self.bbox = im.info["wmf_bbox"]
|
| 49 |
+
|
| 50 |
+
def load(self, im: ImageFile.StubImageFile) -> Image.Image:
|
| 51 |
+
assert im.fp is not None
|
| 52 |
+
im.fp.seek(0) # rewind
|
| 53 |
+
return Image.frombytes(
|
| 54 |
+
"RGB",
|
| 55 |
+
im.size,
|
| 56 |
+
Image.core.drawwmf(im.fp.read(), im.size, self.bbox),
|
| 57 |
+
"raw",
|
| 58 |
+
"BGR",
|
| 59 |
+
(im.size[0] * 3 + 3) & -4,
|
| 60 |
+
-1,
|
| 61 |
+
)
|
| 62 |
+
|
| 63 |
+
register_handler(WmfHandler())
|
| 64 |
+
|
| 65 |
+
#
|
| 66 |
+
# --------------------------------------------------------------------
|
| 67 |
+
# Read WMF file
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def _accept(prefix: bytes) -> bool:
|
| 71 |
+
return prefix.startswith((b"\xd7\xcd\xc6\x9a\x00\x00", b"\x01\x00\x00\x00"))
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
##
|
| 75 |
+
# Image plugin for Windows metafiles.
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
class WmfStubImageFile(ImageFile.StubImageFile):
|
| 79 |
+
format = "WMF"
|
| 80 |
+
format_description = "Windows Metafile"
|
| 81 |
+
|
| 82 |
+
def _open(self) -> None:
|
| 83 |
+
# check placeable header
|
| 84 |
+
assert self.fp is not None
|
| 85 |
+
s = self.fp.read(44)
|
| 86 |
+
|
| 87 |
+
if s.startswith(b"\xd7\xcd\xc6\x9a\x00\x00"):
|
| 88 |
+
# placeable windows metafile
|
| 89 |
+
|
| 90 |
+
# get units per inch
|
| 91 |
+
inch = word(s, 14)
|
| 92 |
+
if inch == 0:
|
| 93 |
+
msg = "Invalid inch"
|
| 94 |
+
raise ValueError(msg)
|
| 95 |
+
self._inch: tuple[float, float] = inch, inch
|
| 96 |
+
|
| 97 |
+
# get bounding box
|
| 98 |
+
x0 = short(s, 6)
|
| 99 |
+
y0 = short(s, 8)
|
| 100 |
+
x1 = short(s, 10)
|
| 101 |
+
y1 = short(s, 12)
|
| 102 |
+
|
| 103 |
+
# normalize size to 72 dots per inch
|
| 104 |
+
self.info["dpi"] = 72
|
| 105 |
+
size = (
|
| 106 |
+
(x1 - x0) * self.info["dpi"] // inch,
|
| 107 |
+
(y1 - y0) * self.info["dpi"] // inch,
|
| 108 |
+
)
|
| 109 |
+
|
| 110 |
+
self.info["wmf_bbox"] = x0, y0, x1, y1
|
| 111 |
+
|
| 112 |
+
# sanity check (standard metafile header)
|
| 113 |
+
if s[22:26] != b"\x01\x00\t\x00":
|
| 114 |
+
msg = "Unsupported WMF file format"
|
| 115 |
+
raise SyntaxError(msg)
|
| 116 |
+
|
| 117 |
+
elif s.startswith(b"\x01\x00\x00\x00") and s[40:44] == b" EMF":
|
| 118 |
+
# enhanced metafile
|
| 119 |
+
|
| 120 |
+
# get bounding box
|
| 121 |
+
x0 = _long(s, 8)
|
| 122 |
+
y0 = _long(s, 12)
|
| 123 |
+
x1 = _long(s, 16)
|
| 124 |
+
y1 = _long(s, 20)
|
| 125 |
+
|
| 126 |
+
# get frame (in 0.01 millimeter units)
|
| 127 |
+
frame = _long(s, 24), _long(s, 28), _long(s, 32), _long(s, 36)
|
| 128 |
+
|
| 129 |
+
size = x1 - x0, y1 - y0
|
| 130 |
+
|
| 131 |
+
# calculate dots per inch from bbox and frame
|
| 132 |
+
xdpi = 2540.0 * (x1 - x0) / (frame[2] - frame[0])
|
| 133 |
+
ydpi = 2540.0 * (y1 - y0) / (frame[3] - frame[1])
|
| 134 |
+
|
| 135 |
+
self.info["wmf_bbox"] = x0, y0, x1, y1
|
| 136 |
+
|
| 137 |
+
if xdpi == ydpi:
|
| 138 |
+
self.info["dpi"] = xdpi
|
| 139 |
+
else:
|
| 140 |
+
self.info["dpi"] = xdpi, ydpi
|
| 141 |
+
self._inch = xdpi, ydpi
|
| 142 |
+
|
| 143 |
+
else:
|
| 144 |
+
msg = "Unsupported file format"
|
| 145 |
+
raise SyntaxError(msg)
|
| 146 |
+
|
| 147 |
+
self._mode = "RGB"
|
| 148 |
+
self._size = size
|
| 149 |
+
|
| 150 |
+
def _load(self) -> ImageFile.StubHandler | None:
|
| 151 |
+
return _handler
|
| 152 |
+
|
| 153 |
+
def load(
|
| 154 |
+
self, dpi: float | tuple[float, float] | None = None
|
| 155 |
+
) -> Image.core.PixelAccess | None:
|
| 156 |
+
if dpi is not None:
|
| 157 |
+
self.info["dpi"] = dpi
|
| 158 |
+
x0, y0, x1, y1 = self.info["wmf_bbox"]
|
| 159 |
+
if not isinstance(dpi, tuple):
|
| 160 |
+
dpi = dpi, dpi
|
| 161 |
+
self._size = (
|
| 162 |
+
int((x1 - x0) * dpi[0] / self._inch[0]),
|
| 163 |
+
int((y1 - y0) * dpi[1] / self._inch[1]),
|
| 164 |
+
)
|
| 165 |
+
return super().load()
|
| 166 |
+
|
| 167 |
+
|
| 168 |
+
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
|
| 169 |
+
if _handler is None or not hasattr(_handler, "save"):
|
| 170 |
+
msg = "WMF save handler not installed"
|
| 171 |
+
raise OSError(msg)
|
| 172 |
+
_handler.save(im, fp, filename)
|
| 173 |
+
|
| 174 |
+
|
| 175 |
+
#
|
| 176 |
+
# --------------------------------------------------------------------
|
| 177 |
+
# Registry stuff
|
| 178 |
+
|
| 179 |
+
|
| 180 |
+
Image.register_open(WmfStubImageFile.format, WmfStubImageFile, _accept)
|
| 181 |
+
Image.register_save(WmfStubImageFile.format, _save)
|
| 182 |
+
|
| 183 |
+
Image.register_extensions(WmfStubImageFile.format, [".wmf", ".emf"])
|
.venv/lib/python3.12/site-packages/PIL/XVThumbImagePlugin.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# The Python Imaging Library.
|
| 3 |
+
# $Id$
|
| 4 |
+
#
|
| 5 |
+
# XV Thumbnail file handler by Charles E. "Gene" Cash
|
| 6 |
+
# (gcash@magicnet.net)
|
| 7 |
+
#
|
| 8 |
+
# see xvcolor.c and xvbrowse.c in the sources to John Bradley's XV,
|
| 9 |
+
# available from ftp://ftp.cis.upenn.edu/pub/xv/
|
| 10 |
+
#
|
| 11 |
+
# history:
|
| 12 |
+
# 98-08-15 cec created (b/w only)
|
| 13 |
+
# 98-12-09 cec added color palette
|
| 14 |
+
# 98-12-28 fl added to PIL (with only a few very minor modifications)
|
| 15 |
+
#
|
| 16 |
+
# To do:
|
| 17 |
+
# FIXME: make save work (this requires quantization support)
|
| 18 |
+
#
|
| 19 |
+
from __future__ import annotations
|
| 20 |
+
|
| 21 |
+
from . import Image, ImageFile, ImagePalette
|
| 22 |
+
from ._binary import o8
|
| 23 |
+
|
| 24 |
+
_MAGIC = b"P7 332"
|
| 25 |
+
|
| 26 |
+
# standard color palette for thumbnails (RGB332)
|
| 27 |
+
PALETTE = b""
|
| 28 |
+
for r in range(8):
|
| 29 |
+
for g in range(8):
|
| 30 |
+
for b in range(4):
|
| 31 |
+
PALETTE = PALETTE + (
|
| 32 |
+
o8((r * 255) // 7) + o8((g * 255) // 7) + o8((b * 255) // 3)
|
| 33 |
+
)
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def _accept(prefix: bytes) -> bool:
|
| 37 |
+
return prefix.startswith(_MAGIC)
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
##
|
| 41 |
+
# Image plugin for XV thumbnail images.
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
class XVThumbImageFile(ImageFile.ImageFile):
|
| 45 |
+
format = "XVThumb"
|
| 46 |
+
format_description = "XV thumbnail image"
|
| 47 |
+
|
| 48 |
+
def _open(self) -> None:
|
| 49 |
+
# check magic
|
| 50 |
+
assert self.fp is not None
|
| 51 |
+
|
| 52 |
+
if not _accept(self.fp.read(6)):
|
| 53 |
+
msg = "not an XV thumbnail file"
|
| 54 |
+
raise SyntaxError(msg)
|
| 55 |
+
|
| 56 |
+
# Skip to beginning of next line
|
| 57 |
+
self.fp.readline()
|
| 58 |
+
|
| 59 |
+
# skip info comments
|
| 60 |
+
while True:
|
| 61 |
+
s = self.fp.readline()
|
| 62 |
+
if not s:
|
| 63 |
+
msg = "Unexpected EOF reading XV thumbnail file"
|
| 64 |
+
raise SyntaxError(msg)
|
| 65 |
+
if s[0] != 35: # ie. when not a comment: '#'
|
| 66 |
+
break
|
| 67 |
+
|
| 68 |
+
# parse header line (already read)
|
| 69 |
+
w, h = s.strip().split(maxsplit=2)[:2]
|
| 70 |
+
|
| 71 |
+
self._mode = "P"
|
| 72 |
+
self._size = int(w), int(h)
|
| 73 |
+
|
| 74 |
+
self.palette = ImagePalette.raw("RGB", PALETTE)
|
| 75 |
+
|
| 76 |
+
self.tile = [
|
| 77 |
+
ImageFile._Tile("raw", (0, 0) + self.size, self.fp.tell(), self.mode)
|
| 78 |
+
]
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
# --------------------------------------------------------------------
|
| 82 |
+
|
| 83 |
+
Image.register_open(XVThumbImageFile.format, XVThumbImageFile, _accept)
|
.venv/lib/python3.12/site-packages/PIL/_imagingft.pyi
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from collections.abc import Callable
|
| 2 |
+
from typing import Any
|
| 3 |
+
|
| 4 |
+
from . import ImageFont, _imaging
|
| 5 |
+
|
| 6 |
+
class Font:
|
| 7 |
+
@property
|
| 8 |
+
def family(self) -> str | None: ...
|
| 9 |
+
@property
|
| 10 |
+
def style(self) -> str | None: ...
|
| 11 |
+
@property
|
| 12 |
+
def ascent(self) -> int: ...
|
| 13 |
+
@property
|
| 14 |
+
def descent(self) -> int: ...
|
| 15 |
+
@property
|
| 16 |
+
def height(self) -> int: ...
|
| 17 |
+
@property
|
| 18 |
+
def x_ppem(self) -> int: ...
|
| 19 |
+
@property
|
| 20 |
+
def y_ppem(self) -> int: ...
|
| 21 |
+
@property
|
| 22 |
+
def glyphs(self) -> int: ...
|
| 23 |
+
def render(
|
| 24 |
+
self,
|
| 25 |
+
string: str | bytes,
|
| 26 |
+
fill: Callable[[int, int], _imaging.ImagingCore],
|
| 27 |
+
mode: str,
|
| 28 |
+
dir: str | None,
|
| 29 |
+
features: list[str] | None,
|
| 30 |
+
lang: str | None,
|
| 31 |
+
stroke_width: float,
|
| 32 |
+
stroke_filled: bool,
|
| 33 |
+
anchor: str | None,
|
| 34 |
+
foreground_ink_long: int,
|
| 35 |
+
start: tuple[float, float],
|
| 36 |
+
/,
|
| 37 |
+
) -> tuple[_imaging.ImagingCore, tuple[int, int]]: ...
|
| 38 |
+
def getsize(
|
| 39 |
+
self,
|
| 40 |
+
string: str | bytes | bytearray,
|
| 41 |
+
mode: str,
|
| 42 |
+
dir: str | None,
|
| 43 |
+
features: list[str] | None,
|
| 44 |
+
lang: str | None,
|
| 45 |
+
anchor: str | None,
|
| 46 |
+
/,
|
| 47 |
+
) -> tuple[tuple[int, int], tuple[int, int]]: ...
|
| 48 |
+
def getlength(
|
| 49 |
+
self,
|
| 50 |
+
string: str | bytes,
|
| 51 |
+
mode: str,
|
| 52 |
+
dir: str | None,
|
| 53 |
+
features: list[str] | None,
|
| 54 |
+
lang: str | None,
|
| 55 |
+
/,
|
| 56 |
+
) -> float: ...
|
| 57 |
+
def getvarnames(self) -> list[bytes]: ...
|
| 58 |
+
def getvaraxes(self) -> list[ImageFont.Axis]: ...
|
| 59 |
+
def setvarname(self, instance_index: int, /) -> None: ...
|
| 60 |
+
def setvaraxes(self, axes: list[float], /) -> None: ...
|
| 61 |
+
|
| 62 |
+
def getfont(
|
| 63 |
+
filename: str | bytes,
|
| 64 |
+
size: float,
|
| 65 |
+
index: int,
|
| 66 |
+
encoding: str,
|
| 67 |
+
font_bytes: bytes,
|
| 68 |
+
layout_engine: int,
|
| 69 |
+
) -> Font: ...
|
| 70 |
+
def __getattr__(name: str) -> Any: ...
|
.venv/lib/python3.12/site-packages/PIL/_webp.pyi
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Any
|
| 2 |
+
|
| 3 |
+
def __getattr__(name: str) -> Any: ...
|
.venv/lib/python3.12/site-packages/audioread/__init__.py
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is part of audioread.
|
| 2 |
+
# Copyright 2013, Adrian Sampson.
|
| 3 |
+
#
|
| 4 |
+
# Permission is hereby granted, free of charge, to any person obtaining
|
| 5 |
+
# a copy of this software and associated documentation files (the
|
| 6 |
+
# "Software"), to deal in the Software without restriction, including
|
| 7 |
+
# without limitation the rights to use, copy, modify, merge, publish,
|
| 8 |
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
| 9 |
+
# permit persons to whom the Software is furnished to do so, subject to
|
| 10 |
+
# the following conditions:
|
| 11 |
+
#
|
| 12 |
+
# The above copyright notice and this permission notice shall be
|
| 13 |
+
# included in all copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
"""Multi-library, cross-platform audio decoding."""
|
| 16 |
+
|
| 17 |
+
from . import ffdec
|
| 18 |
+
from .exceptions import DecodeError, NoBackendError
|
| 19 |
+
from .base import AudioFile # noqa
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
def _gst_available():
|
| 23 |
+
"""Determine whether Gstreamer and the Python GObject bindings are
|
| 24 |
+
installed.
|
| 25 |
+
"""
|
| 26 |
+
try:
|
| 27 |
+
import gi
|
| 28 |
+
except ImportError:
|
| 29 |
+
return False
|
| 30 |
+
|
| 31 |
+
try:
|
| 32 |
+
gi.require_version('Gst', '1.0')
|
| 33 |
+
except (ValueError, AttributeError):
|
| 34 |
+
return False
|
| 35 |
+
|
| 36 |
+
try:
|
| 37 |
+
from gi.repository import Gst # noqa
|
| 38 |
+
except ImportError:
|
| 39 |
+
return False
|
| 40 |
+
|
| 41 |
+
return True
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def _ca_available():
|
| 45 |
+
"""Determines whether CoreAudio is available (i.e., we're running on
|
| 46 |
+
Mac OS X).
|
| 47 |
+
"""
|
| 48 |
+
import ctypes.util
|
| 49 |
+
lib = ctypes.util.find_library('AudioToolbox')
|
| 50 |
+
return lib is not None
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def _mad_available():
|
| 54 |
+
"""Determines whether the pymad bindings are available."""
|
| 55 |
+
try:
|
| 56 |
+
import mad # noqa
|
| 57 |
+
except ImportError:
|
| 58 |
+
return False
|
| 59 |
+
else:
|
| 60 |
+
return True
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
# A cache for the available backends.
|
| 64 |
+
BACKENDS = []
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def available_backends(flush_cache=False):
|
| 68 |
+
"""Returns a list of backends that are available on this system.
|
| 69 |
+
|
| 70 |
+
The list of backends is cached after the first call.
|
| 71 |
+
If the parameter `flush_cache` is set to `True`, then the cache
|
| 72 |
+
will be flushed and the backend list will be reconstructed.
|
| 73 |
+
"""
|
| 74 |
+
|
| 75 |
+
if BACKENDS and not flush_cache:
|
| 76 |
+
return BACKENDS
|
| 77 |
+
|
| 78 |
+
# Standard-library WAV and AIFF readers.
|
| 79 |
+
from . import rawread
|
| 80 |
+
result = [rawread.RawAudioFile]
|
| 81 |
+
|
| 82 |
+
# Core Audio.
|
| 83 |
+
if _ca_available():
|
| 84 |
+
from . import macca
|
| 85 |
+
result.append(macca.ExtAudioFile)
|
| 86 |
+
|
| 87 |
+
# GStreamer.
|
| 88 |
+
if _gst_available():
|
| 89 |
+
from . import gstdec
|
| 90 |
+
result.append(gstdec.GstAudioFile)
|
| 91 |
+
|
| 92 |
+
# MAD.
|
| 93 |
+
if _mad_available():
|
| 94 |
+
from . import maddec
|
| 95 |
+
result.append(maddec.MadAudioFile)
|
| 96 |
+
|
| 97 |
+
# FFmpeg.
|
| 98 |
+
if ffdec.available():
|
| 99 |
+
result.append(ffdec.FFmpegAudioFile)
|
| 100 |
+
|
| 101 |
+
# Cache the backends we found
|
| 102 |
+
BACKENDS[:] = result
|
| 103 |
+
|
| 104 |
+
return BACKENDS
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
def audio_open(path, backends=None):
|
| 108 |
+
"""Open an audio file using a library that is available on this
|
| 109 |
+
system.
|
| 110 |
+
|
| 111 |
+
The optional `backends` parameter can be a list of audio file
|
| 112 |
+
classes to try opening the file with. If it is not provided,
|
| 113 |
+
`audio_open` tries all available backends. If you call this function
|
| 114 |
+
many times, you can avoid the cost of checking for available
|
| 115 |
+
backends every time by calling `available_backends` once and passing
|
| 116 |
+
the result to each `audio_open` call.
|
| 117 |
+
|
| 118 |
+
If all backends fail to read the file, a NoBackendError exception is
|
| 119 |
+
raised.
|
| 120 |
+
"""
|
| 121 |
+
if backends is None:
|
| 122 |
+
backends = available_backends()
|
| 123 |
+
|
| 124 |
+
for BackendClass in backends:
|
| 125 |
+
try:
|
| 126 |
+
return BackendClass(path)
|
| 127 |
+
except DecodeError:
|
| 128 |
+
pass
|
| 129 |
+
|
| 130 |
+
# All backends failed!
|
| 131 |
+
raise NoBackendError()
|
.venv/lib/python3.12/site-packages/audioread/base.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is part of audioread.
|
| 2 |
+
# Copyright 2021, Adrian Sampson.
|
| 3 |
+
#
|
| 4 |
+
# Permission is hereby granted, free of charge, to any person obtaining
|
| 5 |
+
# a copy of this software and associated documentation files (the
|
| 6 |
+
# "Software"), to deal in the Software without restriction, including
|
| 7 |
+
# without limitation the rights to use, copy, modify, merge, publish,
|
| 8 |
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
| 9 |
+
# permit persons to whom the Software is furnished to do so, subject to
|
| 10 |
+
# the following conditions:
|
| 11 |
+
#
|
| 12 |
+
# The above copyright notice and this permission notice shall be
|
| 13 |
+
# included in all copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
class AudioFile:
|
| 17 |
+
"""The base class for all audio file types.
|
| 18 |
+
"""
|
.venv/lib/python3.12/site-packages/audioread/exceptions.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is part of audioread.
|
| 2 |
+
# Copyright 2013, Adrian Sampson.
|
| 3 |
+
#
|
| 4 |
+
# Permission is hereby granted, free of charge, to any person obtaining
|
| 5 |
+
# a copy of this software and associated documentation files (the
|
| 6 |
+
# "Software"), to deal in the Software without restriction, including
|
| 7 |
+
# without limitation the rights to use, copy, modify, merge, publish,
|
| 8 |
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
| 9 |
+
# permit persons to whom the Software is furnished to do so, subject to
|
| 10 |
+
# the following conditions:
|
| 11 |
+
#
|
| 12 |
+
# The above copyright notice and this permission notice shall be
|
| 13 |
+
# included in all copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
class DecodeError(Exception):
|
| 17 |
+
"""The base exception class for all decoding errors raised by this
|
| 18 |
+
package.
|
| 19 |
+
"""
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
class NoBackendError(DecodeError):
|
| 23 |
+
"""The file could not be decoded by any backend. Either no backends
|
| 24 |
+
are available or each available backend failed to decode the file.
|
| 25 |
+
"""
|
.venv/lib/python3.12/site-packages/audioread/ffdec.py
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is part of audioread.
|
| 2 |
+
# Copyright 2014, Adrian Sampson.
|
| 3 |
+
#
|
| 4 |
+
# Permission is hereby granted, free of charge, to any person obtaining
|
| 5 |
+
# a copy of this software and associated documentation files (the
|
| 6 |
+
# "Software"), to deal in the Software without restriction, including
|
| 7 |
+
# without limitation the rights to use, copy, modify, merge, publish,
|
| 8 |
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
| 9 |
+
# permit persons to whom the Software is furnished to do so, subject to
|
| 10 |
+
# the following conditions:
|
| 11 |
+
#
|
| 12 |
+
# The above copyright notice and this permission notice shall be
|
| 13 |
+
# included in all copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
"""Read audio data using the ffmpeg command line tool via its standard
|
| 16 |
+
output.
|
| 17 |
+
"""
|
| 18 |
+
|
| 19 |
+
import queue
|
| 20 |
+
import re
|
| 21 |
+
import subprocess
|
| 22 |
+
import sys
|
| 23 |
+
import threading
|
| 24 |
+
import time
|
| 25 |
+
from io import DEFAULT_BUFFER_SIZE
|
| 26 |
+
|
| 27 |
+
from .exceptions import DecodeError
|
| 28 |
+
from .base import AudioFile
|
| 29 |
+
|
| 30 |
+
COMMANDS = ('ffmpeg', 'avconv')
|
| 31 |
+
|
| 32 |
+
if sys.platform == "win32":
|
| 33 |
+
PROC_FLAGS = 0x08000000
|
| 34 |
+
else:
|
| 35 |
+
PROC_FLAGS = 0
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
class FFmpegError(DecodeError):
|
| 39 |
+
pass
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
class CommunicationError(FFmpegError):
|
| 43 |
+
"""Raised when the output of FFmpeg is not parseable."""
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
class UnsupportedError(FFmpegError):
|
| 47 |
+
"""The file could not be decoded by FFmpeg."""
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
class NotInstalledError(FFmpegError):
|
| 51 |
+
"""Could not find the ffmpeg binary."""
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
class ReadTimeoutError(FFmpegError):
|
| 55 |
+
"""Reading from the ffmpeg command-line tool timed out."""
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
class QueueReaderThread(threading.Thread):
|
| 59 |
+
"""A thread that consumes data from a filehandle and sends the data
|
| 60 |
+
over a Queue.
|
| 61 |
+
"""
|
| 62 |
+
def __init__(self, fh, blocksize=1024, discard=False):
|
| 63 |
+
super().__init__()
|
| 64 |
+
self.fh = fh
|
| 65 |
+
self.blocksize = blocksize
|
| 66 |
+
self.daemon = True
|
| 67 |
+
self.discard = discard
|
| 68 |
+
self.queue = None if discard else queue.Queue()
|
| 69 |
+
|
| 70 |
+
def run(self):
|
| 71 |
+
while True:
|
| 72 |
+
data = self.fh.read(self.blocksize)
|
| 73 |
+
if not self.discard:
|
| 74 |
+
self.queue.put(data)
|
| 75 |
+
if not data:
|
| 76 |
+
# Stream closed (EOF).
|
| 77 |
+
break
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def popen_multiple(commands, command_args, *args, **kwargs):
|
| 81 |
+
"""Like `subprocess.Popen`, but can try multiple commands in case
|
| 82 |
+
some are not available.
|
| 83 |
+
|
| 84 |
+
`commands` is an iterable of command names and `command_args` are
|
| 85 |
+
the rest of the arguments that, when appended to the command name,
|
| 86 |
+
make up the full first argument to `subprocess.Popen`. The
|
| 87 |
+
other positional and keyword arguments are passed through.
|
| 88 |
+
"""
|
| 89 |
+
for i, command in enumerate(commands):
|
| 90 |
+
cmd = [command] + command_args
|
| 91 |
+
try:
|
| 92 |
+
return subprocess.Popen(cmd, *args, **kwargs)
|
| 93 |
+
except OSError:
|
| 94 |
+
if i == len(commands) - 1:
|
| 95 |
+
# No more commands to try.
|
| 96 |
+
raise
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
def available():
|
| 100 |
+
"""Detect whether the FFmpeg backend can be used on this system.
|
| 101 |
+
"""
|
| 102 |
+
try:
|
| 103 |
+
proc = popen_multiple(
|
| 104 |
+
COMMANDS,
|
| 105 |
+
['-version'],
|
| 106 |
+
stdout=subprocess.PIPE,
|
| 107 |
+
stderr=subprocess.PIPE,
|
| 108 |
+
creationflags=PROC_FLAGS,
|
| 109 |
+
)
|
| 110 |
+
except OSError:
|
| 111 |
+
return False
|
| 112 |
+
else:
|
| 113 |
+
proc.communicate()
|
| 114 |
+
return proc.returncode == 0
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
# For Windows error switch management, we need a lock to keep the mode
|
| 118 |
+
# adjustment atomic.
|
| 119 |
+
windows_error_mode_lock = threading.Lock()
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
class FFmpegAudioFile(AudioFile):
|
| 123 |
+
"""An audio file decoded by the ffmpeg command-line utility."""
|
| 124 |
+
def __init__(self, filename, block_size=DEFAULT_BUFFER_SIZE):
|
| 125 |
+
# On Windows, we need to disable the subprocess's crash dialog
|
| 126 |
+
# in case it dies. Passing SEM_NOGPFAULTERRORBOX to SetErrorMode
|
| 127 |
+
# disables this behavior.
|
| 128 |
+
windows = sys.platform.startswith("win")
|
| 129 |
+
if windows:
|
| 130 |
+
windows_error_mode_lock.acquire()
|
| 131 |
+
SEM_NOGPFAULTERRORBOX = 0x0002
|
| 132 |
+
import ctypes
|
| 133 |
+
# We call SetErrorMode in two steps to avoid overriding
|
| 134 |
+
# existing error mode.
|
| 135 |
+
previous_error_mode = \
|
| 136 |
+
ctypes.windll.kernel32.SetErrorMode(SEM_NOGPFAULTERRORBOX)
|
| 137 |
+
ctypes.windll.kernel32.SetErrorMode(
|
| 138 |
+
previous_error_mode | SEM_NOGPFAULTERRORBOX
|
| 139 |
+
)
|
| 140 |
+
|
| 141 |
+
try:
|
| 142 |
+
self.proc = popen_multiple(
|
| 143 |
+
COMMANDS,
|
| 144 |
+
['-i', filename, '-f', 's16le', '-'],
|
| 145 |
+
stdout=subprocess.PIPE,
|
| 146 |
+
stderr=subprocess.PIPE,
|
| 147 |
+
stdin=subprocess.DEVNULL,
|
| 148 |
+
creationflags=PROC_FLAGS,
|
| 149 |
+
)
|
| 150 |
+
|
| 151 |
+
except OSError:
|
| 152 |
+
raise NotInstalledError()
|
| 153 |
+
|
| 154 |
+
finally:
|
| 155 |
+
# Reset previous error mode on Windows. (We can change this
|
| 156 |
+
# back now because the flag was inherited by the subprocess;
|
| 157 |
+
# we don't need to keep it set in the parent process.)
|
| 158 |
+
if windows:
|
| 159 |
+
try:
|
| 160 |
+
import ctypes
|
| 161 |
+
ctypes.windll.kernel32.SetErrorMode(previous_error_mode)
|
| 162 |
+
finally:
|
| 163 |
+
windows_error_mode_lock.release()
|
| 164 |
+
|
| 165 |
+
# Start another thread to consume the standard output of the
|
| 166 |
+
# process, which contains raw audio data.
|
| 167 |
+
self.stdout_reader = QueueReaderThread(self.proc.stdout, block_size)
|
| 168 |
+
self.stdout_reader.start()
|
| 169 |
+
|
| 170 |
+
# Read relevant information from stderr.
|
| 171 |
+
self._get_info()
|
| 172 |
+
|
| 173 |
+
# Start a separate thread to read the rest of the data from
|
| 174 |
+
# stderr. This (a) avoids filling up the OS buffer and (b)
|
| 175 |
+
# collects the error output for diagnosis.
|
| 176 |
+
self.stderr_reader = QueueReaderThread(self.proc.stderr)
|
| 177 |
+
self.stderr_reader.start()
|
| 178 |
+
|
| 179 |
+
def read_data(self, timeout=10.0):
|
| 180 |
+
"""Read blocks of raw PCM data from the file."""
|
| 181 |
+
# Read from stdout in a separate thread and consume data from
|
| 182 |
+
# the queue.
|
| 183 |
+
start_time = time.time()
|
| 184 |
+
while True:
|
| 185 |
+
# Wait for data to be available or a timeout.
|
| 186 |
+
data = None
|
| 187 |
+
try:
|
| 188 |
+
data = self.stdout_reader.queue.get(timeout=timeout)
|
| 189 |
+
if data:
|
| 190 |
+
yield data
|
| 191 |
+
else:
|
| 192 |
+
# End of file.
|
| 193 |
+
break
|
| 194 |
+
except queue.Empty:
|
| 195 |
+
# Queue read timed out.
|
| 196 |
+
end_time = time.time()
|
| 197 |
+
if not data:
|
| 198 |
+
if end_time - start_time >= timeout:
|
| 199 |
+
# Nothing interesting has happened for a while --
|
| 200 |
+
# FFmpeg is probably hanging.
|
| 201 |
+
raise ReadTimeoutError('ffmpeg output: {}'.format(
|
| 202 |
+
b''.join(self.stderr_reader.queue.queue)
|
| 203 |
+
))
|
| 204 |
+
else:
|
| 205 |
+
start_time = end_time
|
| 206 |
+
# Keep waiting.
|
| 207 |
+
continue
|
| 208 |
+
|
| 209 |
+
def _get_info(self):
|
| 210 |
+
"""Reads the tool's output from its stderr stream, extracts the
|
| 211 |
+
relevant information, and parses it.
|
| 212 |
+
"""
|
| 213 |
+
out_parts = []
|
| 214 |
+
while True:
|
| 215 |
+
line = self.proc.stderr.readline()
|
| 216 |
+
if not line:
|
| 217 |
+
# EOF and data not found.
|
| 218 |
+
raise CommunicationError("stream info not found")
|
| 219 |
+
|
| 220 |
+
# In Python 3, result of reading from stderr is bytes.
|
| 221 |
+
if isinstance(line, bytes):
|
| 222 |
+
line = line.decode('utf8', 'ignore')
|
| 223 |
+
|
| 224 |
+
line = line.strip().lower()
|
| 225 |
+
|
| 226 |
+
if 'no such file' in line:
|
| 227 |
+
raise OSError('file not found')
|
| 228 |
+
elif 'invalid data found' in line:
|
| 229 |
+
raise UnsupportedError()
|
| 230 |
+
elif 'duration:' in line:
|
| 231 |
+
out_parts.append(line)
|
| 232 |
+
elif 'audio:' in line:
|
| 233 |
+
out_parts.append(line)
|
| 234 |
+
self._parse_info(''.join(out_parts))
|
| 235 |
+
break
|
| 236 |
+
|
| 237 |
+
def _parse_info(self, s):
|
| 238 |
+
"""Given relevant data from the ffmpeg output, set audio
|
| 239 |
+
parameter fields on this object.
|
| 240 |
+
"""
|
| 241 |
+
# Sample rate.
|
| 242 |
+
match = re.search(r'(\d+) hz', s)
|
| 243 |
+
if match:
|
| 244 |
+
self.samplerate = int(match.group(1))
|
| 245 |
+
else:
|
| 246 |
+
self.samplerate = 0
|
| 247 |
+
|
| 248 |
+
# Channel count.
|
| 249 |
+
match = re.search(r'hz, ([^,]+),', s)
|
| 250 |
+
if match:
|
| 251 |
+
mode = match.group(1)
|
| 252 |
+
if mode == 'stereo':
|
| 253 |
+
self.channels = 2
|
| 254 |
+
else:
|
| 255 |
+
cmatch = re.match(r'(\d+)\.?(\d)?', mode)
|
| 256 |
+
if cmatch:
|
| 257 |
+
self.channels = sum(map(int, cmatch.group().split('.')))
|
| 258 |
+
else:
|
| 259 |
+
self.channels = 1
|
| 260 |
+
else:
|
| 261 |
+
self.channels = 0
|
| 262 |
+
|
| 263 |
+
# Duration.
|
| 264 |
+
match = re.search(
|
| 265 |
+
r'duration: (\d+):(\d+):(\d+).(\d)', s
|
| 266 |
+
)
|
| 267 |
+
if match:
|
| 268 |
+
durparts = list(map(int, match.groups()))
|
| 269 |
+
duration = (
|
| 270 |
+
durparts[0] * 60 * 60 +
|
| 271 |
+
durparts[1] * 60 +
|
| 272 |
+
durparts[2] +
|
| 273 |
+
float(durparts[3]) / 10
|
| 274 |
+
)
|
| 275 |
+
self.duration = duration
|
| 276 |
+
else:
|
| 277 |
+
# No duration found.
|
| 278 |
+
self.duration = 0
|
| 279 |
+
|
| 280 |
+
def close(self):
|
| 281 |
+
"""Close the ffmpeg process used to perform the decoding."""
|
| 282 |
+
if hasattr(self, 'proc'):
|
| 283 |
+
# First check the process's execution status before attempting to
|
| 284 |
+
# kill it. This fixes an issue on Windows Subsystem for Linux where
|
| 285 |
+
# ffmpeg closes normally on its own, but never updates
|
| 286 |
+
# `returncode`.
|
| 287 |
+
self.proc.poll()
|
| 288 |
+
|
| 289 |
+
# Kill the process if it is still running.
|
| 290 |
+
if self.proc.returncode is None:
|
| 291 |
+
self.proc.kill()
|
| 292 |
+
self.proc.wait()
|
| 293 |
+
|
| 294 |
+
# Wait for the stream-reading threads to exit. (They need to
|
| 295 |
+
# stop reading before we can close the streams.)
|
| 296 |
+
if hasattr(self, 'stderr_reader'):
|
| 297 |
+
self.stderr_reader.join()
|
| 298 |
+
if hasattr(self, 'stdout_reader'):
|
| 299 |
+
self.stdout_reader.join()
|
| 300 |
+
|
| 301 |
+
# Close the stdout and stderr streams that were opened by Popen,
|
| 302 |
+
# which should occur regardless of if the process terminated
|
| 303 |
+
# cleanly.
|
| 304 |
+
self.proc.stdout.close()
|
| 305 |
+
self.proc.stderr.close()
|
| 306 |
+
|
| 307 |
+
def __del__(self):
|
| 308 |
+
self.close()
|
| 309 |
+
|
| 310 |
+
# Iteration.
|
| 311 |
+
def __iter__(self):
|
| 312 |
+
return self.read_data()
|
| 313 |
+
|
| 314 |
+
# Context manager.
|
| 315 |
+
def __enter__(self):
|
| 316 |
+
return self
|
| 317 |
+
|
| 318 |
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
| 319 |
+
self.close()
|
| 320 |
+
return False
|
.venv/lib/python3.12/site-packages/audioread/gstdec.py
ADDED
|
@@ -0,0 +1,429 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is part of audioread.
|
| 2 |
+
# Copyright 2011, Adrian Sampson.
|
| 3 |
+
#
|
| 4 |
+
# Permission is hereby granted, free of charge, to any person obtaining
|
| 5 |
+
# a copy of this software and associated documentation files (the
|
| 6 |
+
# "Software"), to deal in the Software without restriction, including
|
| 7 |
+
# without limitation the rights to use, copy, modify, merge, publish,
|
| 8 |
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
| 9 |
+
# permit persons to whom the Software is furnished to do so, subject to
|
| 10 |
+
# the following conditions:
|
| 11 |
+
#
|
| 12 |
+
# The above copyright notice and this permission notice shall be
|
| 13 |
+
# included in all copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
"""Use Gstreamer to decode audio files.
|
| 16 |
+
|
| 17 |
+
To read an audio file, pass it to the constructor for GstAudioFile()
|
| 18 |
+
and then iterate over the contents:
|
| 19 |
+
|
| 20 |
+
>>> f = GstAudioFile('something.mp3')
|
| 21 |
+
>>> try:
|
| 22 |
+
>>> for block in f:
|
| 23 |
+
>>> ...
|
| 24 |
+
>>> finally:
|
| 25 |
+
>>> f.close()
|
| 26 |
+
|
| 27 |
+
Note that there are a few complications caused by Gstreamer's
|
| 28 |
+
asynchronous architecture. This module spawns its own Gobject main-
|
| 29 |
+
loop thread; I'm not sure how that will interact with other main
|
| 30 |
+
loops if your program has them. Also, in order to stop the thread
|
| 31 |
+
and terminate your program normally, you need to call the close()
|
| 32 |
+
method on every GstAudioFile you create. Conveniently, the file can be
|
| 33 |
+
used as a context manager to make this simpler:
|
| 34 |
+
|
| 35 |
+
>>> with GstAudioFile('something.mp3') as f:
|
| 36 |
+
>>> for block in f:
|
| 37 |
+
>>> ...
|
| 38 |
+
|
| 39 |
+
Iterating a GstAudioFile yields strings containing short integer PCM
|
| 40 |
+
data. You can also read the sample rate and channel count from the
|
| 41 |
+
file:
|
| 42 |
+
|
| 43 |
+
>>> with GstAudioFile('something.mp3') as f:
|
| 44 |
+
>>> print f.samplerate
|
| 45 |
+
>>> print f.channels
|
| 46 |
+
>>> print f.duration
|
| 47 |
+
"""
|
| 48 |
+
|
| 49 |
+
import gi
|
| 50 |
+
gi.require_version('Gst', '1.0')
|
| 51 |
+
from gi.repository import GLib, Gst
|
| 52 |
+
|
| 53 |
+
import sys
|
| 54 |
+
import threading
|
| 55 |
+
import os
|
| 56 |
+
import queue
|
| 57 |
+
from urllib.parse import quote
|
| 58 |
+
|
| 59 |
+
from .exceptions import DecodeError
|
| 60 |
+
from .base import AudioFile
|
| 61 |
+
|
| 62 |
+
QUEUE_SIZE = 10
|
| 63 |
+
BUFFER_SIZE = 10
|
| 64 |
+
SENTINEL = '__GSTDEC_SENTINEL__'
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
# Exceptions.
|
| 68 |
+
|
| 69 |
+
class GStreamerError(DecodeError):
|
| 70 |
+
pass
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
class UnknownTypeError(GStreamerError):
|
| 74 |
+
"""Raised when Gstreamer can't decode the given file type."""
|
| 75 |
+
def __init__(self, streaminfo):
|
| 76 |
+
super().__init__(
|
| 77 |
+
"can't decode stream: " + streaminfo
|
| 78 |
+
)
|
| 79 |
+
self.streaminfo = streaminfo
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
class FileReadError(GStreamerError):
|
| 83 |
+
"""Raised when the file can't be read at all."""
|
| 84 |
+
pass
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
class NoStreamError(GStreamerError):
|
| 88 |
+
"""Raised when the file was read successfully but no audio streams
|
| 89 |
+
were found.
|
| 90 |
+
"""
|
| 91 |
+
def __init__(self):
|
| 92 |
+
super().__init__('no audio streams found')
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
class MetadataMissingError(GStreamerError):
|
| 96 |
+
"""Raised when GStreamer fails to report stream metadata (duration,
|
| 97 |
+
channels, or sample rate).
|
| 98 |
+
"""
|
| 99 |
+
pass
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
class IncompleteGStreamerError(GStreamerError):
|
| 103 |
+
"""Raised when necessary components of GStreamer (namely, the
|
| 104 |
+
principal plugin packages) are missing.
|
| 105 |
+
"""
|
| 106 |
+
def __init__(self):
|
| 107 |
+
super().__init__(
|
| 108 |
+
'missing GStreamer base plugins'
|
| 109 |
+
)
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
# Managing the Gobject main loop thread.
|
| 113 |
+
|
| 114 |
+
_shared_loop_thread = None
|
| 115 |
+
_loop_thread_lock = threading.RLock()
|
| 116 |
+
|
| 117 |
+
Gst.init(None)
|
| 118 |
+
|
| 119 |
+
def get_loop_thread():
|
| 120 |
+
"""Get the shared main-loop thread.
|
| 121 |
+
"""
|
| 122 |
+
global _shared_loop_thread
|
| 123 |
+
with _loop_thread_lock:
|
| 124 |
+
if not _shared_loop_thread:
|
| 125 |
+
# Start a new thread.
|
| 126 |
+
_shared_loop_thread = MainLoopThread()
|
| 127 |
+
_shared_loop_thread.start()
|
| 128 |
+
return _shared_loop_thread
|
| 129 |
+
|
| 130 |
+
|
| 131 |
+
class MainLoopThread(threading.Thread):
|
| 132 |
+
"""A daemon thread encapsulating a Gobject main loop.
|
| 133 |
+
"""
|
| 134 |
+
def __init__(self):
|
| 135 |
+
super().__init__()
|
| 136 |
+
self.loop = GLib.MainLoop.new(None, False)
|
| 137 |
+
self.daemon = True
|
| 138 |
+
|
| 139 |
+
def run(self):
|
| 140 |
+
self.loop.run()
|
| 141 |
+
|
| 142 |
+
|
| 143 |
+
# The decoder.
|
| 144 |
+
|
| 145 |
+
class GstAudioFile(AudioFile):
|
| 146 |
+
"""Reads raw audio data from any audio file that Gstreamer
|
| 147 |
+
knows how to decode.
|
| 148 |
+
|
| 149 |
+
>>> with GstAudioFile('something.mp3') as f:
|
| 150 |
+
>>> print f.samplerate
|
| 151 |
+
>>> print f.channels
|
| 152 |
+
>>> print f.duration
|
| 153 |
+
>>> for block in f:
|
| 154 |
+
>>> do_something(block)
|
| 155 |
+
|
| 156 |
+
Iterating the object yields blocks of 16-bit PCM data. Three
|
| 157 |
+
pieces of stream information are also available: samplerate (in Hz),
|
| 158 |
+
number of channels, and duration (in seconds).
|
| 159 |
+
|
| 160 |
+
It's very important that the client call close() when it's done
|
| 161 |
+
with the object. Otherwise, the program is likely to hang on exit.
|
| 162 |
+
Alternatively, of course, one can just use the file as a context
|
| 163 |
+
manager, as shown above.
|
| 164 |
+
"""
|
| 165 |
+
def __init__(self, path):
|
| 166 |
+
self.running = False
|
| 167 |
+
self.finished = False
|
| 168 |
+
|
| 169 |
+
# Set up the Gstreamer pipeline.
|
| 170 |
+
self.pipeline = Gst.Pipeline()
|
| 171 |
+
|
| 172 |
+
self.dec = Gst.ElementFactory.make("uridecodebin", None)
|
| 173 |
+
self.conv = Gst.ElementFactory.make("audioconvert", None)
|
| 174 |
+
self.sink = Gst.ElementFactory.make("appsink", None)
|
| 175 |
+
|
| 176 |
+
if self.dec is None or self.conv is None or self.sink is None:
|
| 177 |
+
# uridecodebin, audioconvert, or appsink is missing. We need
|
| 178 |
+
# gst-plugins-base.
|
| 179 |
+
raise IncompleteGStreamerError()
|
| 180 |
+
|
| 181 |
+
# Register for bus signals.
|
| 182 |
+
bus = self.pipeline.get_bus()
|
| 183 |
+
bus.add_signal_watch()
|
| 184 |
+
bus.connect("message::eos", self._message)
|
| 185 |
+
bus.connect("message::error", self._message)
|
| 186 |
+
|
| 187 |
+
# Configure the input.
|
| 188 |
+
uri = 'file://' + quote(os.path.abspath(path))
|
| 189 |
+
self.dec.set_property("uri", uri)
|
| 190 |
+
# The callback to connect the input.
|
| 191 |
+
self.dec.connect("pad-added", self._pad_added)
|
| 192 |
+
self.dec.connect("no-more-pads", self._no_more_pads)
|
| 193 |
+
# And a callback if decoding fails.
|
| 194 |
+
self.dec.connect("unknown-type", self._unkown_type)
|
| 195 |
+
|
| 196 |
+
# Configure the output.
|
| 197 |
+
# We want short integer data.
|
| 198 |
+
self.sink.set_property(
|
| 199 |
+
'caps',
|
| 200 |
+
Gst.Caps.from_string('audio/x-raw, format=(string)S16LE'),
|
| 201 |
+
)
|
| 202 |
+
# TODO set endianness?
|
| 203 |
+
# Set up the characteristics of the output. We don't want to
|
| 204 |
+
# drop any data (nothing is real-time here); we should bound
|
| 205 |
+
# the memory usage of the internal queue; and, most
|
| 206 |
+
# importantly, setting "sync" to False disables the default
|
| 207 |
+
# behavior in which you consume buffers in real time. This way,
|
| 208 |
+
# we get data as soon as it's decoded.
|
| 209 |
+
self.sink.set_property('drop', False)
|
| 210 |
+
self.sink.set_property('max-buffers', BUFFER_SIZE)
|
| 211 |
+
self.sink.set_property('sync', False)
|
| 212 |
+
# The callback to receive decoded data.
|
| 213 |
+
self.sink.set_property('emit-signals', True)
|
| 214 |
+
self.sink.connect("new-sample", self._new_sample)
|
| 215 |
+
|
| 216 |
+
# We'll need to know when the stream becomes ready and we get
|
| 217 |
+
# its attributes. This semaphore will become available when the
|
| 218 |
+
# caps are received. That way, when __init__() returns, the file
|
| 219 |
+
# (and its attributes) will be ready for reading.
|
| 220 |
+
self.ready_sem = threading.Semaphore(0)
|
| 221 |
+
self.caps_handler = self.sink.get_static_pad("sink").connect(
|
| 222 |
+
"notify::caps", self._notify_caps
|
| 223 |
+
)
|
| 224 |
+
|
| 225 |
+
# Link up everything but the decoder (which must be linked only
|
| 226 |
+
# when it becomes ready).
|
| 227 |
+
self.pipeline.add(self.dec)
|
| 228 |
+
self.pipeline.add(self.conv)
|
| 229 |
+
self.pipeline.add(self.sink)
|
| 230 |
+
|
| 231 |
+
self.conv.link(self.sink)
|
| 232 |
+
|
| 233 |
+
# Set up the queue for data and run the main thread.
|
| 234 |
+
self.queue = queue.Queue(QUEUE_SIZE)
|
| 235 |
+
self.thread = get_loop_thread()
|
| 236 |
+
|
| 237 |
+
# This wil get filled with an exception if opening fails.
|
| 238 |
+
self.read_exc = None
|
| 239 |
+
|
| 240 |
+
# Return as soon as the stream is ready!
|
| 241 |
+
self.running = True
|
| 242 |
+
self.got_caps = False
|
| 243 |
+
self.pipeline.set_state(Gst.State.PLAYING)
|
| 244 |
+
self.ready_sem.acquire()
|
| 245 |
+
if self.read_exc:
|
| 246 |
+
# An error occurred before the stream became ready.
|
| 247 |
+
self.close(True)
|
| 248 |
+
raise self.read_exc
|
| 249 |
+
|
| 250 |
+
# Gstreamer callbacks.
|
| 251 |
+
|
| 252 |
+
def _notify_caps(self, pad, args):
|
| 253 |
+
"""The callback for the sinkpad's "notify::caps" signal.
|
| 254 |
+
"""
|
| 255 |
+
# The sink has started to receive data, so the stream is ready.
|
| 256 |
+
# This also is our opportunity to read information about the
|
| 257 |
+
# stream.
|
| 258 |
+
self.got_caps = True
|
| 259 |
+
info = pad.get_current_caps().get_structure(0)
|
| 260 |
+
|
| 261 |
+
# Stream attributes.
|
| 262 |
+
self.channels = info.get_int('channels')[1]
|
| 263 |
+
self.samplerate = info.get_int('rate')[1]
|
| 264 |
+
|
| 265 |
+
# Query duration.
|
| 266 |
+
success, length = pad.get_peer().query_duration(Gst.Format.TIME)
|
| 267 |
+
if success:
|
| 268 |
+
self.duration = length / 1000000000
|
| 269 |
+
else:
|
| 270 |
+
self.read_exc = MetadataMissingError('duration not available')
|
| 271 |
+
|
| 272 |
+
# Allow constructor to complete.
|
| 273 |
+
self.ready_sem.release()
|
| 274 |
+
|
| 275 |
+
_got_a_pad = False
|
| 276 |
+
|
| 277 |
+
def _pad_added(self, element, pad):
|
| 278 |
+
"""The callback for GstElement's "pad-added" signal.
|
| 279 |
+
"""
|
| 280 |
+
# Decoded data is ready. Connect up the decoder, finally.
|
| 281 |
+
name = pad.query_caps(None).to_string()
|
| 282 |
+
if name.startswith('audio/x-raw'):
|
| 283 |
+
nextpad = self.conv.get_static_pad('sink')
|
| 284 |
+
if not nextpad.is_linked():
|
| 285 |
+
self._got_a_pad = True
|
| 286 |
+
pad.link(nextpad)
|
| 287 |
+
|
| 288 |
+
def _no_more_pads(self, element):
|
| 289 |
+
"""The callback for GstElement's "no-more-pads" signal.
|
| 290 |
+
"""
|
| 291 |
+
# Sent when the pads are done adding (i.e., there are no more
|
| 292 |
+
# streams in the file). If we haven't gotten at least one
|
| 293 |
+
# decodable stream, raise an exception.
|
| 294 |
+
if not self._got_a_pad:
|
| 295 |
+
self.read_exc = NoStreamError()
|
| 296 |
+
self.ready_sem.release() # No effect if we've already started.
|
| 297 |
+
|
| 298 |
+
def _new_sample(self, sink):
|
| 299 |
+
"""The callback for appsink's "new-sample" signal.
|
| 300 |
+
"""
|
| 301 |
+
if self.running:
|
| 302 |
+
# New data is available from the pipeline! Dump it into our
|
| 303 |
+
# queue (or possibly block if we're full).
|
| 304 |
+
buf = sink.emit('pull-sample').get_buffer()
|
| 305 |
+
|
| 306 |
+
# We can't use Gst.Buffer.extract() to read the data as it crashes
|
| 307 |
+
# when called through PyGObject. We also can't use
|
| 308 |
+
# Gst.Buffer.extract_dup() because we have no way in Python to free
|
| 309 |
+
# the memory that it returns. Instead we get access to the actual
|
| 310 |
+
# data via Gst.Memory.map().
|
| 311 |
+
mem = buf.get_all_memory()
|
| 312 |
+
success, info = mem.map(Gst.MapFlags.READ)
|
| 313 |
+
if success:
|
| 314 |
+
if isinstance(info.data, memoryview):
|
| 315 |
+
# We need to copy the data as the memoryview is released
|
| 316 |
+
# when we call mem.unmap()
|
| 317 |
+
data = bytes(info.data)
|
| 318 |
+
else:
|
| 319 |
+
# GStreamer Python bindings <= 1.16 return a copy of the
|
| 320 |
+
# data as bytes()
|
| 321 |
+
data = info.data
|
| 322 |
+
mem.unmap(info)
|
| 323 |
+
self.queue.put(data)
|
| 324 |
+
else:
|
| 325 |
+
raise GStreamerError("Unable to map buffer memory while reading the file.")
|
| 326 |
+
return Gst.FlowReturn.OK
|
| 327 |
+
|
| 328 |
+
def _unkown_type(self, uridecodebin, decodebin, caps):
|
| 329 |
+
"""The callback for decodebin's "unknown-type" signal.
|
| 330 |
+
"""
|
| 331 |
+
# This is called *before* the stream becomes ready when the
|
| 332 |
+
# file can't be read.
|
| 333 |
+
streaminfo = caps.to_string()
|
| 334 |
+
if not streaminfo.startswith('audio/'):
|
| 335 |
+
# Ignore non-audio (e.g., video) decode errors.
|
| 336 |
+
return
|
| 337 |
+
self.read_exc = UnknownTypeError(streaminfo)
|
| 338 |
+
self.ready_sem.release()
|
| 339 |
+
|
| 340 |
+
def _message(self, bus, message):
|
| 341 |
+
"""The callback for GstBus's "message" signal (for two kinds of
|
| 342 |
+
messages).
|
| 343 |
+
"""
|
| 344 |
+
if not self.finished:
|
| 345 |
+
if message.type == Gst.MessageType.EOS:
|
| 346 |
+
# The file is done. Tell the consumer thread.
|
| 347 |
+
self.queue.put(SENTINEL)
|
| 348 |
+
if not self.got_caps:
|
| 349 |
+
# If the stream ends before _notify_caps was called, this
|
| 350 |
+
# is an invalid file.
|
| 351 |
+
self.read_exc = NoStreamError()
|
| 352 |
+
self.ready_sem.release()
|
| 353 |
+
|
| 354 |
+
elif message.type == Gst.MessageType.ERROR:
|
| 355 |
+
gerror, debug = message.parse_error()
|
| 356 |
+
if 'not-linked' in debug:
|
| 357 |
+
self.read_exc = NoStreamError()
|
| 358 |
+
elif 'No such file' in debug:
|
| 359 |
+
self.read_exc = IOError('resource not found')
|
| 360 |
+
else:
|
| 361 |
+
self.read_exc = FileReadError(debug)
|
| 362 |
+
self.ready_sem.release()
|
| 363 |
+
|
| 364 |
+
# Iteration.
|
| 365 |
+
|
| 366 |
+
def __next__(self):
|
| 367 |
+
# Wait for data from the Gstreamer callbacks.
|
| 368 |
+
val = self.queue.get()
|
| 369 |
+
if val == SENTINEL:
|
| 370 |
+
# End of stream.
|
| 371 |
+
raise StopIteration
|
| 372 |
+
return val
|
| 373 |
+
|
| 374 |
+
def __iter__(self):
|
| 375 |
+
return self
|
| 376 |
+
|
| 377 |
+
# Cleanup.
|
| 378 |
+
def close(self, force=False):
|
| 379 |
+
"""Close the file and clean up associated resources.
|
| 380 |
+
|
| 381 |
+
Calling `close()` a second time has no effect.
|
| 382 |
+
"""
|
| 383 |
+
if self.running or force:
|
| 384 |
+
self.running = False
|
| 385 |
+
self.finished = True
|
| 386 |
+
|
| 387 |
+
# Unregister for signals, which we registered for above with
|
| 388 |
+
# `add_signal_watch`. (Without this, GStreamer leaks file
|
| 389 |
+
# descriptors.)
|
| 390 |
+
self.pipeline.get_bus().remove_signal_watch()
|
| 391 |
+
|
| 392 |
+
# Stop reading the file.
|
| 393 |
+
self.dec.set_property("uri", None)
|
| 394 |
+
# Block spurious signals.
|
| 395 |
+
self.sink.get_static_pad("sink").disconnect(self.caps_handler)
|
| 396 |
+
|
| 397 |
+
# Make space in the output queue to let the decoder thread
|
| 398 |
+
# finish. (Otherwise, the thread blocks on its enqueue and
|
| 399 |
+
# the interpreter hangs.)
|
| 400 |
+
try:
|
| 401 |
+
self.queue.get_nowait()
|
| 402 |
+
except queue.Empty:
|
| 403 |
+
pass
|
| 404 |
+
|
| 405 |
+
# Halt the pipeline (closing file).
|
| 406 |
+
self.pipeline.set_state(Gst.State.NULL)
|
| 407 |
+
|
| 408 |
+
def __del__(self):
|
| 409 |
+
self.close()
|
| 410 |
+
|
| 411 |
+
# Context manager.
|
| 412 |
+
def __enter__(self):
|
| 413 |
+
return self
|
| 414 |
+
|
| 415 |
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
| 416 |
+
self.close()
|
| 417 |
+
return False
|
| 418 |
+
|
| 419 |
+
|
| 420 |
+
# Smoke test.
|
| 421 |
+
if __name__ == '__main__':
|
| 422 |
+
for path in sys.argv[1:]:
|
| 423 |
+
path = os.path.abspath(os.path.expanduser(path))
|
| 424 |
+
with GstAudioFile(path) as f:
|
| 425 |
+
print(f.channels)
|
| 426 |
+
print(f.samplerate)
|
| 427 |
+
print(f.duration)
|
| 428 |
+
for s in f:
|
| 429 |
+
print(len(s), ord(s[0]))
|
.venv/lib/python3.12/site-packages/audioread/macca.py
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is part of audioread.
|
| 2 |
+
# Copyright 2011, Adrian Sampson.
|
| 3 |
+
#
|
| 4 |
+
# Permission is hereby granted, free of charge, to any person obtaining
|
| 5 |
+
# a copy of this software and associated documentation files (the
|
| 6 |
+
# "Software"), to deal in the Software without restriction, including
|
| 7 |
+
# without limitation the rights to use, copy, modify, merge, publish,
|
| 8 |
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
| 9 |
+
# permit persons to whom the Software is furnished to do so, subject to
|
| 10 |
+
# the following conditions:
|
| 11 |
+
#
|
| 12 |
+
# The above copyright notice and this permission notice shall be
|
| 13 |
+
# included in all copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
"""Read audio files using CoreAudio on Mac OS X."""
|
| 16 |
+
import copy
|
| 17 |
+
import ctypes
|
| 18 |
+
import ctypes.util
|
| 19 |
+
import os
|
| 20 |
+
import sys
|
| 21 |
+
|
| 22 |
+
from .exceptions import DecodeError
|
| 23 |
+
from .base import AudioFile
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
# CoreFoundation and CoreAudio libraries along with their function
|
| 27 |
+
# prototypes.
|
| 28 |
+
|
| 29 |
+
def _load_framework(name):
|
| 30 |
+
return ctypes.cdll.LoadLibrary(ctypes.util.find_library(name))
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
_coreaudio = _load_framework('AudioToolbox')
|
| 34 |
+
_corefoundation = _load_framework('CoreFoundation')
|
| 35 |
+
|
| 36 |
+
# Convert CFStrings to C strings.
|
| 37 |
+
_corefoundation.CFStringGetCStringPtr.restype = ctypes.c_char_p
|
| 38 |
+
_corefoundation.CFStringGetCStringPtr.argtypes = [ctypes.c_void_p,
|
| 39 |
+
ctypes.c_int]
|
| 40 |
+
|
| 41 |
+
# Free memory.
|
| 42 |
+
_corefoundation.CFRelease.argtypes = [ctypes.c_void_p]
|
| 43 |
+
|
| 44 |
+
# Create a file:// URL.
|
| 45 |
+
_corefoundation.CFURLCreateFromFileSystemRepresentation.restype = \
|
| 46 |
+
ctypes.c_void_p
|
| 47 |
+
_corefoundation.CFURLCreateFromFileSystemRepresentation.argtypes = \
|
| 48 |
+
[ctypes.c_int, ctypes.c_char_p, ctypes.c_int, ctypes.c_bool]
|
| 49 |
+
|
| 50 |
+
# Get a string representation of a URL.
|
| 51 |
+
_corefoundation.CFURLGetString.restype = ctypes.c_void_p
|
| 52 |
+
_corefoundation.CFURLGetString.argtypes = [ctypes.c_void_p]
|
| 53 |
+
|
| 54 |
+
# Open an audio file for reading.
|
| 55 |
+
_coreaudio.ExtAudioFileOpenURL.restype = ctypes.c_int
|
| 56 |
+
_coreaudio.ExtAudioFileOpenURL.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
|
| 57 |
+
|
| 58 |
+
# Set audio file property.
|
| 59 |
+
_coreaudio.ExtAudioFileSetProperty.restype = ctypes.c_int
|
| 60 |
+
_coreaudio.ExtAudioFileSetProperty.argtypes = \
|
| 61 |
+
[ctypes.c_void_p, ctypes.c_uint, ctypes.c_uint, ctypes.c_void_p]
|
| 62 |
+
|
| 63 |
+
# Get audio file property.
|
| 64 |
+
_coreaudio.ExtAudioFileGetProperty.restype = ctypes.c_int
|
| 65 |
+
_coreaudio.ExtAudioFileGetProperty.argtypes = \
|
| 66 |
+
[ctypes.c_void_p, ctypes.c_uint, ctypes.c_void_p, ctypes.c_void_p]
|
| 67 |
+
|
| 68 |
+
# Read from an audio file.
|
| 69 |
+
_coreaudio.ExtAudioFileRead.restype = ctypes.c_int
|
| 70 |
+
_coreaudio.ExtAudioFileRead.argtypes = \
|
| 71 |
+
[ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
|
| 72 |
+
|
| 73 |
+
# Close/free an audio file.
|
| 74 |
+
_coreaudio.ExtAudioFileDispose.restype = ctypes.c_int
|
| 75 |
+
_coreaudio.ExtAudioFileDispose.argtypes = [ctypes.c_void_p]
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
# Constants used in CoreAudio.
|
| 79 |
+
|
| 80 |
+
def multi_char_literal(chars):
|
| 81 |
+
"""Emulates character integer literals in C. Given a string "abc",
|
| 82 |
+
returns the value of the C single-quoted literal 'abc'.
|
| 83 |
+
"""
|
| 84 |
+
num = 0
|
| 85 |
+
for index, char in enumerate(chars):
|
| 86 |
+
shift = (len(chars) - index - 1) * 8
|
| 87 |
+
num |= ord(char) << shift
|
| 88 |
+
return num
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
PROP_FILE_DATA_FORMAT = multi_char_literal('ffmt')
|
| 92 |
+
PROP_CLIENT_DATA_FORMAT = multi_char_literal('cfmt')
|
| 93 |
+
PROP_LENGTH = multi_char_literal('#frm')
|
| 94 |
+
AUDIO_ID_PCM = multi_char_literal('lpcm')
|
| 95 |
+
PCM_IS_FLOAT = 1 << 0
|
| 96 |
+
PCM_IS_BIG_ENDIAN = 1 << 1
|
| 97 |
+
PCM_IS_SIGNED_INT = 1 << 2
|
| 98 |
+
PCM_IS_PACKED = 1 << 3
|
| 99 |
+
ERROR_TYPE = multi_char_literal('typ?')
|
| 100 |
+
ERROR_FORMAT = multi_char_literal('fmt?')
|
| 101 |
+
ERROR_NOT_FOUND = -43
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
# Check for errors in functions that return error codes.
|
| 105 |
+
|
| 106 |
+
class MacError(DecodeError):
|
| 107 |
+
def __init__(self, code):
|
| 108 |
+
if code == ERROR_TYPE:
|
| 109 |
+
msg = 'unsupported audio type'
|
| 110 |
+
elif code == ERROR_FORMAT:
|
| 111 |
+
msg = 'unsupported format'
|
| 112 |
+
else:
|
| 113 |
+
msg = 'error %i' % code
|
| 114 |
+
super().__init__(msg)
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
def check(err):
|
| 118 |
+
"""If err is nonzero, raise a MacError exception."""
|
| 119 |
+
if err == ERROR_NOT_FOUND:
|
| 120 |
+
raise OSError('file not found')
|
| 121 |
+
elif err != 0:
|
| 122 |
+
raise MacError(err)
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
# CoreFoundation objects.
|
| 126 |
+
|
| 127 |
+
class CFObject:
|
| 128 |
+
def __init__(self, obj):
|
| 129 |
+
if obj == 0:
|
| 130 |
+
raise ValueError('object is zero')
|
| 131 |
+
self._obj = obj
|
| 132 |
+
|
| 133 |
+
def __del__(self):
|
| 134 |
+
if _corefoundation:
|
| 135 |
+
_corefoundation.CFRelease(self._obj)
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
class CFURL(CFObject):
|
| 139 |
+
def __init__(self, filename):
|
| 140 |
+
filename = os.path.abspath(os.path.expanduser(filename))
|
| 141 |
+
if not isinstance(filename, bytes):
|
| 142 |
+
filename = filename.encode(sys.getfilesystemencoding())
|
| 143 |
+
url = _corefoundation.CFURLCreateFromFileSystemRepresentation(
|
| 144 |
+
0, filename, len(filename), False
|
| 145 |
+
)
|
| 146 |
+
super().__init__(url)
|
| 147 |
+
|
| 148 |
+
def __str__(self):
|
| 149 |
+
cfstr = _corefoundation.CFURLGetString(self._obj)
|
| 150 |
+
out = _corefoundation.CFStringGetCStringPtr(cfstr, 0)
|
| 151 |
+
# Resulting CFString does not need to be released according to docs.
|
| 152 |
+
return out
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
# Structs used in CoreAudio.
|
| 156 |
+
|
| 157 |
+
class AudioStreamBasicDescription(ctypes.Structure):
|
| 158 |
+
_fields_ = [
|
| 159 |
+
("mSampleRate", ctypes.c_double),
|
| 160 |
+
("mFormatID", ctypes.c_uint),
|
| 161 |
+
("mFormatFlags", ctypes.c_uint),
|
| 162 |
+
("mBytesPerPacket", ctypes.c_uint),
|
| 163 |
+
("mFramesPerPacket", ctypes.c_uint),
|
| 164 |
+
("mBytesPerFrame", ctypes.c_uint),
|
| 165 |
+
("mChannelsPerFrame", ctypes.c_uint),
|
| 166 |
+
("mBitsPerChannel", ctypes.c_uint),
|
| 167 |
+
("mReserved", ctypes.c_uint),
|
| 168 |
+
]
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
class AudioBuffer(ctypes.Structure):
|
| 172 |
+
_fields_ = [
|
| 173 |
+
("mNumberChannels", ctypes.c_uint),
|
| 174 |
+
("mDataByteSize", ctypes.c_uint),
|
| 175 |
+
("mData", ctypes.c_void_p),
|
| 176 |
+
]
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
class AudioBufferList(ctypes.Structure):
|
| 180 |
+
_fields_ = [
|
| 181 |
+
("mNumberBuffers", ctypes.c_uint),
|
| 182 |
+
("mBuffers", AudioBuffer * 1),
|
| 183 |
+
]
|
| 184 |
+
|
| 185 |
+
|
| 186 |
+
# Main functionality.
|
| 187 |
+
|
| 188 |
+
class ExtAudioFile(AudioFile):
|
| 189 |
+
"""A CoreAudio "extended audio file". Reads information and raw PCM
|
| 190 |
+
audio data from any file that CoreAudio knows how to decode.
|
| 191 |
+
|
| 192 |
+
>>> with ExtAudioFile('something.m4a') as f:
|
| 193 |
+
>>> print f.samplerate
|
| 194 |
+
>>> print f.channels
|
| 195 |
+
>>> print f.duration
|
| 196 |
+
>>> for block in f:
|
| 197 |
+
>>> do_something(block)
|
| 198 |
+
|
| 199 |
+
"""
|
| 200 |
+
def __init__(self, filename):
|
| 201 |
+
url = CFURL(filename)
|
| 202 |
+
try:
|
| 203 |
+
self._obj = self._open_url(url)
|
| 204 |
+
except:
|
| 205 |
+
self.closed = True
|
| 206 |
+
raise
|
| 207 |
+
del url
|
| 208 |
+
|
| 209 |
+
self.closed = False
|
| 210 |
+
self._file_fmt = None
|
| 211 |
+
self._client_fmt = None
|
| 212 |
+
|
| 213 |
+
self.setup()
|
| 214 |
+
|
| 215 |
+
@classmethod
|
| 216 |
+
def _open_url(cls, url):
|
| 217 |
+
"""Given a CFURL Python object, return an opened ExtAudioFileRef.
|
| 218 |
+
"""
|
| 219 |
+
file_obj = ctypes.c_void_p()
|
| 220 |
+
check(_coreaudio.ExtAudioFileOpenURL(
|
| 221 |
+
url._obj, ctypes.byref(file_obj)
|
| 222 |
+
))
|
| 223 |
+
return file_obj
|
| 224 |
+
|
| 225 |
+
def set_client_format(self, desc):
|
| 226 |
+
"""Get the client format description. This describes the
|
| 227 |
+
encoding of the data that the program will read from this
|
| 228 |
+
object.
|
| 229 |
+
"""
|
| 230 |
+
assert desc.mFormatID == AUDIO_ID_PCM
|
| 231 |
+
check(_coreaudio.ExtAudioFileSetProperty(
|
| 232 |
+
self._obj, PROP_CLIENT_DATA_FORMAT, ctypes.sizeof(desc),
|
| 233 |
+
ctypes.byref(desc)
|
| 234 |
+
))
|
| 235 |
+
self._client_fmt = desc
|
| 236 |
+
|
| 237 |
+
def get_file_format(self):
|
| 238 |
+
"""Get the file format description. This describes the type of
|
| 239 |
+
data stored on disk.
|
| 240 |
+
"""
|
| 241 |
+
# Have cached file format?
|
| 242 |
+
if self._file_fmt is not None:
|
| 243 |
+
return self._file_fmt
|
| 244 |
+
|
| 245 |
+
# Make the call to retrieve it.
|
| 246 |
+
desc = AudioStreamBasicDescription()
|
| 247 |
+
size = ctypes.c_int(ctypes.sizeof(desc))
|
| 248 |
+
check(_coreaudio.ExtAudioFileGetProperty(
|
| 249 |
+
self._obj, PROP_FILE_DATA_FORMAT, ctypes.byref(size),
|
| 250 |
+
ctypes.byref(desc)
|
| 251 |
+
))
|
| 252 |
+
|
| 253 |
+
# Cache result.
|
| 254 |
+
self._file_fmt = desc
|
| 255 |
+
return desc
|
| 256 |
+
|
| 257 |
+
@property
|
| 258 |
+
def channels(self):
|
| 259 |
+
"""The number of channels in the audio source."""
|
| 260 |
+
return int(self.get_file_format().mChannelsPerFrame)
|
| 261 |
+
|
| 262 |
+
@property
|
| 263 |
+
def samplerate(self):
|
| 264 |
+
"""Gets the sample rate of the audio."""
|
| 265 |
+
return int(self.get_file_format().mSampleRate)
|
| 266 |
+
|
| 267 |
+
@property
|
| 268 |
+
def duration(self):
|
| 269 |
+
"""Gets the length of the file in seconds (a float)."""
|
| 270 |
+
return float(self.nframes) / self.samplerate
|
| 271 |
+
|
| 272 |
+
@property
|
| 273 |
+
def nframes(self):
|
| 274 |
+
"""Gets the number of frames in the source file."""
|
| 275 |
+
length = ctypes.c_long()
|
| 276 |
+
size = ctypes.c_int(ctypes.sizeof(length))
|
| 277 |
+
check(_coreaudio.ExtAudioFileGetProperty(
|
| 278 |
+
self._obj, PROP_LENGTH, ctypes.byref(size), ctypes.byref(length)
|
| 279 |
+
))
|
| 280 |
+
return length.value
|
| 281 |
+
|
| 282 |
+
def setup(self, bitdepth=16):
|
| 283 |
+
"""Set the client format parameters, specifying the desired PCM
|
| 284 |
+
audio data format to be read from the file. Must be called
|
| 285 |
+
before reading from the file.
|
| 286 |
+
"""
|
| 287 |
+
fmt = self.get_file_format()
|
| 288 |
+
newfmt = copy.copy(fmt)
|
| 289 |
+
|
| 290 |
+
newfmt.mFormatID = AUDIO_ID_PCM
|
| 291 |
+
newfmt.mFormatFlags = \
|
| 292 |
+
PCM_IS_SIGNED_INT | PCM_IS_PACKED
|
| 293 |
+
newfmt.mBitsPerChannel = bitdepth
|
| 294 |
+
newfmt.mBytesPerPacket = \
|
| 295 |
+
(fmt.mChannelsPerFrame * newfmt.mBitsPerChannel // 8)
|
| 296 |
+
newfmt.mFramesPerPacket = 1
|
| 297 |
+
newfmt.mBytesPerFrame = newfmt.mBytesPerPacket
|
| 298 |
+
self.set_client_format(newfmt)
|
| 299 |
+
|
| 300 |
+
def read_data(self, blocksize=4096):
|
| 301 |
+
"""Generates byte strings reflecting the audio data in the file.
|
| 302 |
+
"""
|
| 303 |
+
frames = ctypes.c_uint(blocksize // self._client_fmt.mBytesPerFrame)
|
| 304 |
+
buf = ctypes.create_string_buffer(blocksize)
|
| 305 |
+
|
| 306 |
+
buflist = AudioBufferList()
|
| 307 |
+
buflist.mNumberBuffers = 1
|
| 308 |
+
buflist.mBuffers[0].mNumberChannels = \
|
| 309 |
+
self._client_fmt.mChannelsPerFrame
|
| 310 |
+
buflist.mBuffers[0].mDataByteSize = blocksize
|
| 311 |
+
buflist.mBuffers[0].mData = ctypes.cast(buf, ctypes.c_void_p)
|
| 312 |
+
|
| 313 |
+
while True:
|
| 314 |
+
check(_coreaudio.ExtAudioFileRead(
|
| 315 |
+
self._obj, ctypes.byref(frames), ctypes.byref(buflist)
|
| 316 |
+
))
|
| 317 |
+
|
| 318 |
+
assert buflist.mNumberBuffers == 1
|
| 319 |
+
size = buflist.mBuffers[0].mDataByteSize
|
| 320 |
+
if not size:
|
| 321 |
+
break
|
| 322 |
+
|
| 323 |
+
data = ctypes.cast(buflist.mBuffers[0].mData,
|
| 324 |
+
ctypes.POINTER(ctypes.c_char))
|
| 325 |
+
blob = data[:size]
|
| 326 |
+
yield blob
|
| 327 |
+
|
| 328 |
+
def close(self):
|
| 329 |
+
"""Close the audio file and free associated memory."""
|
| 330 |
+
if not self.closed:
|
| 331 |
+
check(_coreaudio.ExtAudioFileDispose(self._obj))
|
| 332 |
+
self.closed = True
|
| 333 |
+
|
| 334 |
+
def __del__(self):
|
| 335 |
+
if _coreaudio:
|
| 336 |
+
self.close()
|
| 337 |
+
|
| 338 |
+
# Context manager methods.
|
| 339 |
+
def __enter__(self):
|
| 340 |
+
return self
|
| 341 |
+
|
| 342 |
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
| 343 |
+
self.close()
|
| 344 |
+
return False
|
| 345 |
+
|
| 346 |
+
# Iteration.
|
| 347 |
+
def __iter__(self):
|
| 348 |
+
return self.read_data()
|
.venv/lib/python3.12/site-packages/audioread/maddec.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is part of audioread.
|
| 2 |
+
# Copyright 2011, Adrian Sampson.
|
| 3 |
+
#
|
| 4 |
+
# Permission is hereby granted, free of charge, to any person obtaining
|
| 5 |
+
# a copy of this software and associated documentation files (the
|
| 6 |
+
# "Software"), to deal in the Software without restriction, including
|
| 7 |
+
# without limitation the rights to use, copy, modify, merge, publish,
|
| 8 |
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
| 9 |
+
# permit persons to whom the Software is furnished to do so, subject to
|
| 10 |
+
# the following conditions:
|
| 11 |
+
#
|
| 12 |
+
# The above copyright notice and this permission notice shall be
|
| 13 |
+
# included in all copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
"""Decode MPEG audio files with MAD (via pymad)."""
|
| 16 |
+
import mad
|
| 17 |
+
|
| 18 |
+
from . import DecodeError
|
| 19 |
+
from .base import AudioFile
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
class UnsupportedError(DecodeError):
|
| 23 |
+
"""The file is not readable by MAD."""
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
class MadAudioFile(AudioFile):
|
| 27 |
+
"""MPEG audio file decoder using the MAD library."""
|
| 28 |
+
def __init__(self, filename):
|
| 29 |
+
self.fp = open(filename, 'rb')
|
| 30 |
+
self.mf = mad.MadFile(self.fp)
|
| 31 |
+
if not self.mf.total_time(): # Indicates a failed open.
|
| 32 |
+
self.fp.close()
|
| 33 |
+
raise UnsupportedError()
|
| 34 |
+
|
| 35 |
+
def close(self):
|
| 36 |
+
if hasattr(self, 'fp'):
|
| 37 |
+
self.fp.close()
|
| 38 |
+
if hasattr(self, 'mf'):
|
| 39 |
+
del self.mf
|
| 40 |
+
|
| 41 |
+
def read_blocks(self, block_size=4096):
|
| 42 |
+
"""Generates buffers containing PCM data for the audio file.
|
| 43 |
+
"""
|
| 44 |
+
while True:
|
| 45 |
+
out = self.mf.read(block_size)
|
| 46 |
+
if not out:
|
| 47 |
+
break
|
| 48 |
+
yield bytes(out)
|
| 49 |
+
|
| 50 |
+
@property
|
| 51 |
+
def samplerate(self):
|
| 52 |
+
"""Sample rate in Hz."""
|
| 53 |
+
return self.mf.samplerate()
|
| 54 |
+
|
| 55 |
+
@property
|
| 56 |
+
def duration(self):
|
| 57 |
+
"""Length of the audio in seconds (a float)."""
|
| 58 |
+
return float(self.mf.total_time()) / 1000
|
| 59 |
+
|
| 60 |
+
@property
|
| 61 |
+
def channels(self):
|
| 62 |
+
"""The number of channels."""
|
| 63 |
+
if self.mf.mode() == mad.MODE_SINGLE_CHANNEL:
|
| 64 |
+
return 1
|
| 65 |
+
elif self.mf.mode() in (mad.MODE_DUAL_CHANNEL,
|
| 66 |
+
mad.MODE_JOINT_STEREO,
|
| 67 |
+
mad.MODE_STEREO):
|
| 68 |
+
return 2
|
| 69 |
+
else:
|
| 70 |
+
# Other mode?
|
| 71 |
+
return 2
|
| 72 |
+
|
| 73 |
+
def __del__(self):
|
| 74 |
+
self.close()
|
| 75 |
+
|
| 76 |
+
# Iteration.
|
| 77 |
+
def __iter__(self):
|
| 78 |
+
return self.read_blocks()
|
| 79 |
+
|
| 80 |
+
# Context manager.
|
| 81 |
+
def __enter__(self):
|
| 82 |
+
return self
|
| 83 |
+
|
| 84 |
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
| 85 |
+
self.close()
|
| 86 |
+
return False
|
.venv/lib/python3.12/site-packages/audioread/rawread.py
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is part of audioread.
|
| 2 |
+
# Copyright 2011, Adrian Sampson.
|
| 3 |
+
#
|
| 4 |
+
# Permission is hereby granted, free of charge, to any person obtaining
|
| 5 |
+
# a copy of this software and associated documentation files (the
|
| 6 |
+
# "Software"), to deal in the Software without restriction, including
|
| 7 |
+
# without limitation the rights to use, copy, modify, merge, publish,
|
| 8 |
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
| 9 |
+
# permit persons to whom the Software is furnished to do so, subject to
|
| 10 |
+
# the following conditions:
|
| 11 |
+
#
|
| 12 |
+
# The above copyright notice and this permission notice shall be
|
| 13 |
+
# included in all copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
"""Uses standard-library modules to read AIFF, AIFF-C, and WAV files."""
|
| 16 |
+
import aifc
|
| 17 |
+
import audioop
|
| 18 |
+
import struct
|
| 19 |
+
import sunau
|
| 20 |
+
import wave
|
| 21 |
+
|
| 22 |
+
from .exceptions import DecodeError
|
| 23 |
+
from .base import AudioFile
|
| 24 |
+
|
| 25 |
+
# Produce two-byte (16-bit) output samples.
|
| 26 |
+
TARGET_WIDTH = 2
|
| 27 |
+
|
| 28 |
+
# Python 3.4 added support for 24-bit (3-byte) samples.
|
| 29 |
+
SUPPORTED_WIDTHS = (1, 2, 3, 4)
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
class UnsupportedError(DecodeError):
|
| 33 |
+
"""File is not an AIFF, WAV, or Au file."""
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
class BitWidthError(DecodeError):
|
| 37 |
+
"""The file uses an unsupported bit width."""
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def byteswap(s):
|
| 41 |
+
"""Swaps the endianness of the bytestring s, which must be an array
|
| 42 |
+
of shorts (16-bit signed integers). This is probably less efficient
|
| 43 |
+
than it should be.
|
| 44 |
+
"""
|
| 45 |
+
assert len(s) % 2 == 0
|
| 46 |
+
parts = []
|
| 47 |
+
for i in range(0, len(s), 2):
|
| 48 |
+
chunk = s[i:i + 2]
|
| 49 |
+
newchunk = struct.pack('<h', *struct.unpack('>h', chunk))
|
| 50 |
+
parts.append(newchunk)
|
| 51 |
+
return b''.join(parts)
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
class RawAudioFile(AudioFile):
|
| 55 |
+
"""An AIFF, WAV, or Au file that can be read by the Python standard
|
| 56 |
+
library modules ``wave``, ``aifc``, and ``sunau``.
|
| 57 |
+
"""
|
| 58 |
+
def __init__(self, filename):
|
| 59 |
+
self._fh = open(filename, 'rb')
|
| 60 |
+
|
| 61 |
+
try:
|
| 62 |
+
self._file = aifc.open(self._fh)
|
| 63 |
+
except aifc.Error:
|
| 64 |
+
# Return to the beginning of the file to try the next reader.
|
| 65 |
+
self._fh.seek(0)
|
| 66 |
+
else:
|
| 67 |
+
self._needs_byteswap = True
|
| 68 |
+
self._check()
|
| 69 |
+
return
|
| 70 |
+
|
| 71 |
+
try:
|
| 72 |
+
self._file = wave.open(self._fh)
|
| 73 |
+
except wave.Error:
|
| 74 |
+
self._fh.seek(0)
|
| 75 |
+
pass
|
| 76 |
+
else:
|
| 77 |
+
self._needs_byteswap = False
|
| 78 |
+
self._check()
|
| 79 |
+
return
|
| 80 |
+
|
| 81 |
+
try:
|
| 82 |
+
self._file = sunau.open(self._fh)
|
| 83 |
+
except sunau.Error:
|
| 84 |
+
self._fh.seek(0)
|
| 85 |
+
pass
|
| 86 |
+
else:
|
| 87 |
+
self._needs_byteswap = True
|
| 88 |
+
self._check()
|
| 89 |
+
return
|
| 90 |
+
|
| 91 |
+
# None of the three libraries could open the file.
|
| 92 |
+
self._fh.close()
|
| 93 |
+
raise UnsupportedError()
|
| 94 |
+
|
| 95 |
+
def _check(self):
|
| 96 |
+
"""Check that the files' parameters allow us to decode it and
|
| 97 |
+
raise an error otherwise.
|
| 98 |
+
"""
|
| 99 |
+
if self._file.getsampwidth() not in SUPPORTED_WIDTHS:
|
| 100 |
+
self.close()
|
| 101 |
+
raise BitWidthError()
|
| 102 |
+
|
| 103 |
+
def close(self):
|
| 104 |
+
"""Close the underlying file."""
|
| 105 |
+
self._file.close()
|
| 106 |
+
self._fh.close()
|
| 107 |
+
|
| 108 |
+
@property
|
| 109 |
+
def channels(self):
|
| 110 |
+
"""Number of audio channels."""
|
| 111 |
+
return self._file.getnchannels()
|
| 112 |
+
|
| 113 |
+
@property
|
| 114 |
+
def samplerate(self):
|
| 115 |
+
"""Sample rate in Hz."""
|
| 116 |
+
return self._file.getframerate()
|
| 117 |
+
|
| 118 |
+
@property
|
| 119 |
+
def duration(self):
|
| 120 |
+
"""Length of the audio in seconds (a float)."""
|
| 121 |
+
return float(self._file.getnframes()) / self.samplerate
|
| 122 |
+
|
| 123 |
+
def read_data(self, block_samples=1024):
|
| 124 |
+
"""Generates blocks of PCM data found in the file."""
|
| 125 |
+
old_width = self._file.getsampwidth()
|
| 126 |
+
|
| 127 |
+
while True:
|
| 128 |
+
data = self._file.readframes(block_samples)
|
| 129 |
+
if not data:
|
| 130 |
+
break
|
| 131 |
+
|
| 132 |
+
# Make sure we have the desired bitdepth and endianness.
|
| 133 |
+
data = audioop.lin2lin(data, old_width, TARGET_WIDTH)
|
| 134 |
+
if self._needs_byteswap and self._file.getcomptype() != 'sowt':
|
| 135 |
+
# Big-endian data. Swap endianness.
|
| 136 |
+
data = byteswap(data)
|
| 137 |
+
yield data
|
| 138 |
+
|
| 139 |
+
# Context manager.
|
| 140 |
+
def __enter__(self):
|
| 141 |
+
return self
|
| 142 |
+
|
| 143 |
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
| 144 |
+
self.close()
|
| 145 |
+
return False
|
| 146 |
+
|
| 147 |
+
# Iteration.
|
| 148 |
+
def __iter__(self):
|
| 149 |
+
return self.read_data()
|
.venv/lib/python3.12/site-packages/babel-2.18.0.dist-info/INSTALLER
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
uv
|
.venv/lib/python3.12/site-packages/babel-2.18.0.dist-info/METADATA
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Metadata-Version: 2.4
|
| 2 |
+
Name: babel
|
| 3 |
+
Version: 2.18.0
|
| 4 |
+
Summary: Internationalization utilities
|
| 5 |
+
Home-page: https://babel.pocoo.org/
|
| 6 |
+
Author: Armin Ronacher
|
| 7 |
+
Author-email: armin.ronacher@active-4.com
|
| 8 |
+
Maintainer: Aarni Koskela
|
| 9 |
+
Maintainer-email: akx@iki.fi
|
| 10 |
+
License: BSD-3-Clause
|
| 11 |
+
Project-URL: Source, https://github.com/python-babel/babel
|
| 12 |
+
Classifier: Development Status :: 5 - Production/Stable
|
| 13 |
+
Classifier: Environment :: Web Environment
|
| 14 |
+
Classifier: Intended Audience :: Developers
|
| 15 |
+
Classifier: License :: OSI Approved :: BSD License
|
| 16 |
+
Classifier: Operating System :: OS Independent
|
| 17 |
+
Classifier: Programming Language :: Python
|
| 18 |
+
Classifier: Programming Language :: Python :: 3
|
| 19 |
+
Classifier: Programming Language :: Python :: 3 :: Only
|
| 20 |
+
Classifier: Programming Language :: Python :: 3.8
|
| 21 |
+
Classifier: Programming Language :: Python :: 3.9
|
| 22 |
+
Classifier: Programming Language :: Python :: 3.10
|
| 23 |
+
Classifier: Programming Language :: Python :: 3.11
|
| 24 |
+
Classifier: Programming Language :: Python :: 3.12
|
| 25 |
+
Classifier: Programming Language :: Python :: 3.13
|
| 26 |
+
Classifier: Programming Language :: Python :: 3.14
|
| 27 |
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
| 28 |
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
| 29 |
+
Classifier: Topic :: Software Development :: Internationalization
|
| 30 |
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
| 31 |
+
Requires-Python: >=3.8
|
| 32 |
+
License-File: LICENSE
|
| 33 |
+
Requires-Dist: pytz>=2015.7; python_version < "3.9"
|
| 34 |
+
Provides-Extra: dev
|
| 35 |
+
Requires-Dist: tzdata; sys_platform == "win32" and extra == "dev"
|
| 36 |
+
Requires-Dist: backports.zoneinfo; python_version < "3.9" and extra == "dev"
|
| 37 |
+
Requires-Dist: freezegun~=1.0; extra == "dev"
|
| 38 |
+
Requires-Dist: jinja2>=3.0; extra == "dev"
|
| 39 |
+
Requires-Dist: pytest-cov; extra == "dev"
|
| 40 |
+
Requires-Dist: pytest>=6.0; extra == "dev"
|
| 41 |
+
Requires-Dist: pytz; extra == "dev"
|
| 42 |
+
Requires-Dist: setuptools; extra == "dev"
|
| 43 |
+
Dynamic: author
|
| 44 |
+
Dynamic: author-email
|
| 45 |
+
Dynamic: classifier
|
| 46 |
+
Dynamic: description
|
| 47 |
+
Dynamic: home-page
|
| 48 |
+
Dynamic: license
|
| 49 |
+
Dynamic: license-file
|
| 50 |
+
Dynamic: maintainer
|
| 51 |
+
Dynamic: maintainer-email
|
| 52 |
+
Dynamic: project-url
|
| 53 |
+
Dynamic: provides-extra
|
| 54 |
+
Dynamic: requires-dist
|
| 55 |
+
Dynamic: requires-python
|
| 56 |
+
Dynamic: summary
|
| 57 |
+
|
| 58 |
+
A collection of tools for internationalizing Python applications.
|
.venv/lib/python3.12/site-packages/babel-2.18.0.dist-info/RECORD
ADDED
|
@@ -0,0 +1,1122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
../../../bin/pybabel,sha256=530NII8_xt4aO6Vyf8ySVPeBNaMxi7sFbfxN1kd-G5M,329
|
| 2 |
+
babel-2.18.0.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2
|
| 3 |
+
babel-2.18.0.dist-info/METADATA,sha256=ETmbwDprgf0g6LgoIzkgUqjblpqO8VA4Kwz1mWr89Bo,2222
|
| 4 |
+
babel-2.18.0.dist-info/RECORD,,
|
| 5 |
+
babel-2.18.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 6 |
+
babel-2.18.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
| 7 |
+
babel-2.18.0.dist-info/entry_points.txt,sha256=Y2Cr1P3E8Yt7kqzvVz4wnTvD1H3-BVD4FOkVqHIGBfc,750
|
| 8 |
+
babel-2.18.0.dist-info/licenses/LICENSE,sha256=hrrVdYx4WboGJR-PEu7oheyjE2mSPfsrh6fBPDY02HA,1531
|
| 9 |
+
babel-2.18.0.dist-info/top_level.txt,sha256=mQO3vNkqlcYs_xRaL5EpRIy1IRjMp4N9_vdwmiemPXo,6
|
| 10 |
+
babel/__init__.py,sha256=iAtaegCgnkkqd3t4mTON700DPw6YvOeVn-zdWKrGhEM,838
|
| 11 |
+
babel/core.py,sha256=47mzcxFpj3j16ZV7VhvZOdJQWBo4rlutQBD0oqM6G7g,45775
|
| 12 |
+
babel/dates.py,sha256=jRsuCS09RAsW8gqixQk23Ffn69FieZU85fDNTiAzL-8,76060
|
| 13 |
+
babel/global.dat,sha256=o4ncdOHrpbYBw8e0F8jQe55B8Zk3DRDMLMcMdxdxFW4,461219
|
| 14 |
+
babel/languages.py,sha256=vySUM88KPgjZIfp8F98rzg0eBWUxBp4VSv3daVZzQrI,2866
|
| 15 |
+
babel/lists.py,sha256=AGtv7uAV6lz4bs4F9OBZ1zcMctNsC_w8_ClJJT7D4LA,4380
|
| 16 |
+
babel/locale-data/LICENSE.unicode,sha256=tMCujvBPcFn5bOW74EZ_n-b22Bu-E1F3Ad_rlh-00LY,2033
|
| 17 |
+
babel/locale-data/aa.dat,sha256=CI5kOVaXWX2CQoHT6AXhrOMwFPCiQyd7Wke2QBJ1UtE,2795
|
| 18 |
+
babel/locale-data/aa_DJ.dat,sha256=VKjSgKVsftG91nj0-AQMYFuF_p4YAGfRkgAvycB2EYU,1112
|
| 19 |
+
babel/locale-data/aa_ER.dat,sha256=6b6qROwoeOq0-batM1Z7Ji2gvGDogl3ODcftt1Jkm9g,637
|
| 20 |
+
babel/locale-data/aa_ET.dat,sha256=piwFu94H7e-jPwd4ZaWiDc-j2nAH_GiC5UZ2IxMx7bs,635
|
| 21 |
+
babel/locale-data/ab.dat,sha256=xeio1NLBNIAXcafnonWjO3w0zofwM-aKr0-RiaL7pRQ,95311
|
| 22 |
+
babel/locale-data/ab_GE.dat,sha256=b5be2Uv1YtP-bkMasJMzoQPxJPNLFqifXnCiK8rCyLE,635
|
| 23 |
+
babel/locale-data/af.dat,sha256=pO9_3BpJSQAJ3gZ_j6ZdUpGq3zqEv6CIZZ-CpJTXwr4,144732
|
| 24 |
+
babel/locale-data/af_NA.dat,sha256=zif__TyNY44mSCYOCrrglsyr_H31JhBNPwSJftg8200,1450
|
| 25 |
+
babel/locale-data/af_ZA.dat,sha256=6lT-mLg7LRtyAEhWhiF2xVtiPyzEa28U6hsFw_BMrZE,635
|
| 26 |
+
babel/locale-data/agq.dat,sha256=JJbF6NFR9qwwQTrIyrLh04DFJniIqDuFsbmHDGu5ThM,16628
|
| 27 |
+
babel/locale-data/agq_CM.dat,sha256=hYtg7pRw7J6TsYHvhlEEv7DqpyXoK3KS9DAqtYtgBX0,636
|
| 28 |
+
babel/locale-data/ak.dat,sha256=L73y_ylhZy39SlEaAwA4jCqP_92qLvIlsagl-o2RlKE,116224
|
| 29 |
+
babel/locale-data/ak_GH.dat,sha256=tM-OSpXWyBwZFfKPVStWBbFv3dwNj_7AqcBz4ONrOQs,616
|
| 30 |
+
babel/locale-data/am.dat,sha256=TddfeRISFvzjTFpB-vH3gjSKs2r8iT3CYckrriibXZY,173260
|
| 31 |
+
babel/locale-data/am_ET.dat,sha256=2VZDSh5bY9vLLuTqcKYG66p5OYlvPRPX58rpNTFWPok,635
|
| 32 |
+
babel/locale-data/an.dat,sha256=a1gEztcqWoMLW3f5_jlDxcPsYY-ItHKVud7gjisrS4E,28050
|
| 33 |
+
babel/locale-data/an_ES.dat,sha256=rQuq-zKj7-fCjY-5fGGoGJT1x60pAyCEAVEswXPnHrI,653
|
| 34 |
+
babel/locale-data/ann.dat,sha256=fUenvOdPjqayLEiVDRNncK8SOBi9gAGAdxMuOATlsI0,737
|
| 35 |
+
babel/locale-data/ann_NG.dat,sha256=0i2K6cv6eCurgFgwtiCr09hYwZCA1kHkQaKnDyCD86M,617
|
| 36 |
+
babel/locale-data/apc.dat,sha256=G96W-ebLqQlTuPN3-VqSfAY-GF0K99c6uXHza5f4e2g,1564
|
| 37 |
+
babel/locale-data/apc_SY.dat,sha256=tagFeQz8BA9Pc7RMqkce1ZalfKIBjqg0SR4NlpGQaaM,679
|
| 38 |
+
babel/locale-data/ar.dat,sha256=yAijlkkaH-RgRQidvCyNBkpi9Z7OTC9cNfIbKo4n4gk,288582
|
| 39 |
+
babel/locale-data/ar_001.dat,sha256=hRKDI3wzxO5T191MfSdCn_MZ6ckM2Rz_r__0JZqS00s,1707
|
| 40 |
+
babel/locale-data/ar_AE.dat,sha256=hEbIYUoNE5mRLOVXhmkGsvT0NAcq-rxs51VIMMzG9LY,982
|
| 41 |
+
babel/locale-data/ar_BH.dat,sha256=FoQ2c3E3TDqKcioarWBvLi_MllJmSd_56r0U45_gHWw,720
|
| 42 |
+
babel/locale-data/ar_DJ.dat,sha256=qbNam_QAmhobsIUfJLCL9pe146SvcmNIE_L3cWpmkBs,698
|
| 43 |
+
babel/locale-data/ar_DZ.dat,sha256=_Y-JLC5hincnxze7sGmEpb7N4JnBh7LdFdaVPcSMDvM,1263
|
| 44 |
+
babel/locale-data/ar_EG.dat,sha256=qE3gLQ6BzLaBOPNJVgaBhPQiIL2kQ4AiD_jLl7o52IM,720
|
| 45 |
+
babel/locale-data/ar_EH.dat,sha256=a0xJdGJYzGFzfvwxZVDP7yURlTm93FQSTQ5qp3XDMYo,658
|
| 46 |
+
babel/locale-data/ar_ER.dat,sha256=l-WjJfxm7kP05-Hnr5PingHaKWJ46ScfW4KEBcwD5HM,679
|
| 47 |
+
babel/locale-data/ar_IL.dat,sha256=O3UYAjf4BB3NdcSQTn-RzNjyj4kzTBhX3q7E8-9Aihw,1264
|
| 48 |
+
babel/locale-data/ar_IQ.dat,sha256=7-DnoHqsoBDe-ZXe0rIcEotb-F_CFyChc73dwnXuUoE,1975
|
| 49 |
+
babel/locale-data/ar_JO.dat,sha256=hT1z-Me5SOjul3BHFubcqlyEk9H57fwD4EFENddiVt8,1398
|
| 50 |
+
babel/locale-data/ar_KM.dat,sha256=Zx5XtfTuRPiW6iViOjeal_Fq-18EA7GuERViMP1_mc4,1230
|
| 51 |
+
babel/locale-data/ar_KW.dat,sha256=1wSXHTcgFKwhNciVS8IvGKvkzzqOIMBFykEJEQXdhEE,720
|
| 52 |
+
babel/locale-data/ar_LB.dat,sha256=-SuXO6LdhXNi4f_PHNrlxl8iXX47perQ_oS19bwRGpI,1414
|
| 53 |
+
babel/locale-data/ar_LY.dat,sha256=2OxSGD1gkiWPcaRHd1qQv9ifG82WEjGahKqhsoFXfnY,1249
|
| 54 |
+
babel/locale-data/ar_MA.dat,sha256=hTOwsXC8tsJxBVlksxmAMlIkn4kK50juJa6TuAPFkp0,1559
|
| 55 |
+
babel/locale-data/ar_MR.dat,sha256=Kq7uT5LxvYXnGWz-cVcI6yDNximu9hZIpoKydmVse78,1359
|
| 56 |
+
babel/locale-data/ar_OM.dat,sha256=HVOqTfoH3JVTHJL-yDBiIafNfckU7CIcO_sIzXBffKw,720
|
| 57 |
+
babel/locale-data/ar_PS.dat,sha256=F-HZRPcMe_tJ8r9V01h-7mQ0UKQxQmuWuXNSi94MVMM,1336
|
| 58 |
+
babel/locale-data/ar_QA.dat,sha256=UKfLpyX856fNgeifdr22wXpDncirWJi9NxqfSnS-7fw,720
|
| 59 |
+
babel/locale-data/ar_SA.dat,sha256=8WE8HwCwO-OT_G2JBSgmPWSzyHOdIA3zajXPbBZr2Tg,24787
|
| 60 |
+
babel/locale-data/ar_SD.dat,sha256=f7aUKlrKmmC7ijTjVwn5r9m3mfZfEob1a7GHVCj4Qxk,720
|
| 61 |
+
babel/locale-data/ar_SO.dat,sha256=4LD_gds2VsvxdFHpFo56CxTFenzNdvEkMofc4oTGBTU,677
|
| 62 |
+
babel/locale-data/ar_SS.dat,sha256=T6eeWPeFejmBC7InKqg-6qmWoer1vjl6srHe_5ybkDU,700
|
| 63 |
+
babel/locale-data/ar_SY.dat,sha256=u42uhje_zt806WlUMpp5sIdi1yjw3Yv7vYbl6aELsyc,1398
|
| 64 |
+
babel/locale-data/ar_TD.dat,sha256=OG7NYtRrJiDeRt7HP-B4ta5ri-6fdSnYomppfy2A4ec,658
|
| 65 |
+
babel/locale-data/ar_TN.dat,sha256=xO974NyO5T-pRs-5b55sfQFGIwU2Y4q3VQUeqtqWf80,1201
|
| 66 |
+
babel/locale-data/ar_YE.dat,sha256=vu8wYJgzcJ1douKfKLx3-hAg1sjndD5_PTHWG_bzRL0,720
|
| 67 |
+
babel/locale-data/arn.dat,sha256=JB-QfwCOVQbVrLRlq2LMxU6SHO-V4ZaU2_0W15-0Rfs,721
|
| 68 |
+
babel/locale-data/arn_CL.dat,sha256=cf_JrdIAxFwbltVwtloNC9527Du7zaoBDM-_KmctSvE,636
|
| 69 |
+
babel/locale-data/as.dat,sha256=xoTmhieoAVjw59h2-_pLp0wjfZPVvYMV6qDSJjLrjq8,209876
|
| 70 |
+
babel/locale-data/as_IN.dat,sha256=bE-OZ0Y3d2-QtD23ztjluSsFk1_RFNYMFzKgBC3waw4,658
|
| 71 |
+
babel/locale-data/asa.dat,sha256=zzPu7L8RV8SVEKqeRiGIoWLBCJkeS0acDh0pYq87qMI,15492
|
| 72 |
+
babel/locale-data/asa_TZ.dat,sha256=U0GU10aP58LxCeqyjl69RQCZi_6tTQxm2vni6XVkoqY,617
|
| 73 |
+
babel/locale-data/ast.dat,sha256=_Qeoc0gz1ag9MkmNIuv4ufVjk0fH5xtW4M7vp8ST4hY,168961
|
| 74 |
+
babel/locale-data/ast_ES.dat,sha256=51kFxigV5COuiPiNisp-OBFYMith5rUgBmU48rGk7Hc,654
|
| 75 |
+
babel/locale-data/az.dat,sha256=2EcwMc8qIqCW_F0Ic2XjFQthkCGyfLNzJzJZU99ZcaA,173802
|
| 76 |
+
babel/locale-data/az_Arab.dat,sha256=IGBla73oKavlLHhtIW37idHxTkmQWZ-S8NE54b65d4k,7499
|
| 77 |
+
babel/locale-data/az_Arab_IQ.dat,sha256=VsM0-KQPCP4MUw-2wMsBv-F467cr2Bup3jfxx8Fc3ZE,678
|
| 78 |
+
babel/locale-data/az_Arab_IR.dat,sha256=ROb0gFTPwK5CcjpQMB7CJ662eld9sZj7IA6QMrvxgto,678
|
| 79 |
+
babel/locale-data/az_Arab_TR.dat,sha256=EV6cNf3keBNREHkfF98GGZGOZz4L5dxf8pFbujInaQY,635
|
| 80 |
+
babel/locale-data/az_Cyrl.dat,sha256=ru4QYee174toLQsGPJn-d6xe65FsLQ87vBV9AW0o4D8,35540
|
| 81 |
+
babel/locale-data/az_Cyrl_AZ.dat,sha256=GRZjR-gp6JYeLNxoiAKNdv9bkTmS1bpYnRJ0c9YIGws,635
|
| 82 |
+
babel/locale-data/az_Latn.dat,sha256=aK2ziytg5Ig6GYk9tVCq4BEyV6UYy9Ip7F1_i4Pq1jw,2258
|
| 83 |
+
babel/locale-data/az_Latn_AZ.dat,sha256=GRZjR-gp6JYeLNxoiAKNdv9bkTmS1bpYnRJ0c9YIGws,635
|
| 84 |
+
babel/locale-data/ba.dat,sha256=Ly1V4wBNM4KCDGtuy9oCug4fZzVNEFqXOI8XKhkWFOQ,732
|
| 85 |
+
babel/locale-data/ba_RU.dat,sha256=8YcwUOx3h4BcSfUIumKJ4wcFyiSgBM74SqenVIQUKi8,653
|
| 86 |
+
babel/locale-data/bal.dat,sha256=mYMTNzej_lac3GimNq9dYgLY3Q4RtXpEvUkQ-zfzVqw,12849
|
| 87 |
+
babel/locale-data/bal_Arab.dat,sha256=25CVl5rF7FqKEeHzAmt0BccVI_ODqmMP86KqQ4i6PL8,934
|
| 88 |
+
babel/locale-data/bal_Arab_PK.dat,sha256=sy4tpUtN1St5yFoTp8C6-vi2bFGPjSaG_zDbY16Q988,636
|
| 89 |
+
babel/locale-data/bal_Latn.dat,sha256=X9sEvC7SU0VUFnapzFKUq0nvc1az1c9lHmrCPHPCg4U,116909
|
| 90 |
+
babel/locale-data/bal_Latn_PK.dat,sha256=sy4tpUtN1St5yFoTp8C6-vi2bFGPjSaG_zDbY16Q988,636
|
| 91 |
+
babel/locale-data/bas.dat,sha256=hts2-gooZheGxndoyiVM9NwFrAitthfb4IPr7TtYb2U,16673
|
| 92 |
+
babel/locale-data/bas_CM.dat,sha256=WBq-_rOvkBnT5pBaCyq844LLSRReQzg2HM0u7GmhKKM,636
|
| 93 |
+
babel/locale-data/be.dat,sha256=8L6Q0C4wjbLMC9I7ltFoY1prATuRd-8nn0udprYBI6A,272322
|
| 94 |
+
babel/locale-data/be_BY.dat,sha256=yN4Rf2-HqinMscTfe4jKEYpsCEaddHce6K25ol595Ag,635
|
| 95 |
+
babel/locale-data/be_TARASK.dat,sha256=93xDxO06nuAugpWjrnx6C5k8Fs26HIAolUcUPuoHhbg,104118
|
| 96 |
+
babel/locale-data/bem.dat,sha256=zBh5HxY-hRgaQd95anmqMAPP0UVzSV7JdcuqtJ78t1c,5782
|
| 97 |
+
babel/locale-data/bem_ZM.dat,sha256=nQvsLK0FOSlgf6wspQdbj00IveO62c2Mvxjzn4eHGSs,617
|
| 98 |
+
babel/locale-data/bew.dat,sha256=mfKR23PSPyS0AHxbaSuMvufZZQlMICxDGuPv78MtDbU,122095
|
| 99 |
+
babel/locale-data/bew_ID.dat,sha256=JWKbnUQc4ZsJYTcBFypK3gSyFRK6Kp8UFEqdytnPMnM,636
|
| 100 |
+
babel/locale-data/bez.dat,sha256=_saESrmbxsbQnGLACykFIs-aLUC-N7IigpyPWGLBebI,16300
|
| 101 |
+
babel/locale-data/bez_TZ.dat,sha256=OwcKelhUxQWu-8Jm9nf2vCay6-8LQvg-ueZSN_mrGz0,617
|
| 102 |
+
babel/locale-data/bg.dat,sha256=ofd_Tv4onIP1cE1pVO-171ySR9JJXuHKzpWqc-vtLP8,227940
|
| 103 |
+
babel/locale-data/bg_BG.dat,sha256=CERFyuC4Dw9BfAZapqaq69iKAp7rBXWNCkLWAL5tAhQ,653
|
| 104 |
+
babel/locale-data/bgc.dat,sha256=gW0lkQNX_h1SATbqzIqe0twmGqqfigkbqo7gvBCG1AI,2493
|
| 105 |
+
babel/locale-data/bgc_IN.dat,sha256=hO39nPiyUx1kfCdagpCQ8lzPLycjdfk59jFQgsd3Qec,659
|
| 106 |
+
babel/locale-data/bgn.dat,sha256=8RKzmGYGYkn5IF7NHRgPtaI9ozwCeEKoUE4aXQpItKY,28964
|
| 107 |
+
babel/locale-data/bgn_AE.dat,sha256=5jo7AWXMNdiiEf-RqzB5xRVj0R89NFdwq5RAIEAeeRE,636
|
| 108 |
+
babel/locale-data/bgn_AF.dat,sha256=UXCb78n57adZBdKHEGnhbmeVYppzlSscVOWnQNxfJOQ,679
|
| 109 |
+
babel/locale-data/bgn_IR.dat,sha256=iXxyPD5Z-ouDWFpOE2atoi6-HHGoD6PNaT9c-TH6x7o,679
|
| 110 |
+
babel/locale-data/bgn_OM.dat,sha256=3O0CzFrjWxOQFdN6-lDhCxRngoXfadd_dwYoVyjK9jA,679
|
| 111 |
+
babel/locale-data/bgn_PK.dat,sha256=gdVUcc-isHd9lf0S-AmFoPIMwDZ8ay6NY4o1udWI6Yo,636
|
| 112 |
+
babel/locale-data/bho.dat,sha256=JQAEhmajFwUOKB7ACN1-ZPcoKcXJaq0-FhsFCVcvn_8,2875
|
| 113 |
+
babel/locale-data/bho_IN.dat,sha256=UcL_aZq35dOHME0Fux9zyt9B6BOTxyR5UvaGWKLs1jE,659
|
| 114 |
+
babel/locale-data/blo.dat,sha256=I0gfsGv80xf7do-oxzjkh2or934YxYgDMkM9RHf7UXk,168499
|
| 115 |
+
babel/locale-data/blo_BJ.dat,sha256=LM79oUzVI4JtLYEUklfbQxoweFAslN9jS-Ex-dya0mE,617
|
| 116 |
+
babel/locale-data/blt.dat,sha256=6G2E9osBy9OrG1iUKLD9cwcRk3IV7fT11iI8zFkLaeo,723
|
| 117 |
+
babel/locale-data/blt_VN.dat,sha256=vpTQEJYssmuBUn_pYqx7ZtYONNNz02_oBYlDMdWqKAc,636
|
| 118 |
+
babel/locale-data/bm.dat,sha256=K0dLlxoDfJb4QLwa_D0SXfrbD53Xed_EJ21843fY9hY,15798
|
| 119 |
+
babel/locale-data/bm_ML.dat,sha256=PAGrUwc1S6q32DDHTu5LkePFXe_M_i_WxIY4oLuUnzw,616
|
| 120 |
+
babel/locale-data/bm_Nkoo.dat,sha256=UiQ-oKSXYmbnUj9nNXi-9Afx2taBc5EiN-JM1huGOno,2805
|
| 121 |
+
babel/locale-data/bm_Nkoo_ML.dat,sha256=PAGrUwc1S6q32DDHTu5LkePFXe_M_i_WxIY4oLuUnzw,616
|
| 122 |
+
babel/locale-data/bn.dat,sha256=00cRKYrwyk5snhrekLj0TQBVzZlV_PjQ0aLlsApgwxw,219185
|
| 123 |
+
babel/locale-data/bn_BD.dat,sha256=mVW90kQmhDcwzKmkmgNAt5iMq1pLWmNndNID9fspVjY,635
|
| 124 |
+
babel/locale-data/bn_IN.dat,sha256=Y4d5tMv6rG2A1fTcfN7-cMeZ1iH8XuqdZgpEBUy_FTg,4035
|
| 125 |
+
babel/locale-data/bo.dat,sha256=2eVqnOFPv04Ix-1FVPHlDQ9UVTQC1JtC7-5lQ89aX7A,20102
|
| 126 |
+
babel/locale-data/bo_CN.dat,sha256=xOnyre81Z1IHnWV5mJH0x313h-ZWu84hIXcMuB50IT0,635
|
| 127 |
+
babel/locale-data/bo_IN.dat,sha256=GvYCgtrOD5zYYsfMtVmkCv8-y6His8Lg7iuytEGjnMI,1307
|
| 128 |
+
babel/locale-data/br.dat,sha256=rBs1Bp9H6Q4ECO2mouoJmnCW0ux5CLPx1zy32GvpkCo,272612
|
| 129 |
+
babel/locale-data/br_FR.dat,sha256=3oVDdZd7Xf4Q-hwmYraF42SM_3NtvSoiZlmlh6gSNOs,653
|
| 130 |
+
babel/locale-data/brx.dat,sha256=0L8rfQwjwtj3y5M5zzdEB10way4I9P2m8A2E0mTIcac,160164
|
| 131 |
+
babel/locale-data/brx_IN.dat,sha256=NKuJh0cEhRQasy6JAGUi5HbqdnhhEFTQ_7osgtdG5Iw,659
|
| 132 |
+
babel/locale-data/bs.dat,sha256=YVLbXGLHf6QZ9vYnCjxjO3uBImuYnoxR-cEuBPVbP_w,213968
|
| 133 |
+
babel/locale-data/bs_Cyrl.dat,sha256=oqFwEFFfYqyzkVvswj8CR2B_RCb51Myv8jQaDDjz0u8,219235
|
| 134 |
+
babel/locale-data/bs_Cyrl_BA.dat,sha256=oA7rsQckE_IxCpXXB3F3KWQwM3WZTR7WAdYxJN98oeM,635
|
| 135 |
+
babel/locale-data/bs_Latn.dat,sha256=6L9SY85hONRHO4Jz389C2Ziy7llKcDoyVNiE96ozCJ8,1990
|
| 136 |
+
babel/locale-data/bs_Latn_BA.dat,sha256=oA7rsQckE_IxCpXXB3F3KWQwM3WZTR7WAdYxJN98oeM,635
|
| 137 |
+
babel/locale-data/bss.dat,sha256=n9LaBwBIJ7adjJ63G7Q9o00llhPJtkgmeEp08nAa4D4,978
|
| 138 |
+
babel/locale-data/bss_CM.dat,sha256=TD7ixCHREfOLDsDJn8FY5YqGYH9czdEzdULCIl_0GhM,636
|
| 139 |
+
babel/locale-data/byn.dat,sha256=qT32E4jh6H_qm7HYSsAbKmaKluaLrGNXNl3F3FivncE,13403
|
| 140 |
+
babel/locale-data/byn_ER.dat,sha256=oAaZEqMJuTbMITO-ZO6gg8qjwROukzh5VgjtLp6rqD4,617
|
| 141 |
+
babel/locale-data/ca.dat,sha256=CIT0-7X7_e8RKWRrhLSmG-aBC2D51-hvRrTV-7iBav8,184038
|
| 142 |
+
babel/locale-data/ca_AD.dat,sha256=tsLumbhbbeXw627WKi-sQdSTFwNpcSRvJIEYcrOMqOM,653
|
| 143 |
+
babel/locale-data/ca_ES.dat,sha256=T-zv3FfnCJA2WUQTeBADKV82ghY-r60wk8mXtD9wbnI,653
|
| 144 |
+
babel/locale-data/ca_ES_VALENCIA.dat,sha256=7Q59_PX0VWyLsDkC-qscZ-dKJ9AFzz7kCzJz4fTdBWY,2976
|
| 145 |
+
babel/locale-data/ca_FR.dat,sha256=5HUFYUl5QRaUMwJxGLIqUhDO4_wF_crrr346wJmEOZo,672
|
| 146 |
+
babel/locale-data/ca_IT.dat,sha256=Zh2rtOq8MIDC2CQXWnhp5HOvPfXNxhRGnnZViOgc1Mg,653
|
| 147 |
+
babel/locale-data/cad.dat,sha256=XxlMk1b9CWE3wERhhQQN0wxW7iq8Mrngb05RXenmaSI,2476
|
| 148 |
+
babel/locale-data/cad_US.dat,sha256=FWV1sofgr9no5P9yBxNDLeKWoQd80XEYEilmLwamkSc,654
|
| 149 |
+
babel/locale-data/cch.dat,sha256=J4S73psT7C_cXs1VNNYow47plBodQ4PKINC59kzvfAw,2430
|
| 150 |
+
babel/locale-data/cch_NG.dat,sha256=0adhw9xNMlVEqDVKvHe4HCPtbjcw5NSo4ny_pOjl0-4,617
|
| 151 |
+
babel/locale-data/ccp.dat,sha256=Jn_O5MwN6DMGxNrXUpdrhT_z5ZOYh3-Sm5yGUcV8bII,207292
|
| 152 |
+
babel/locale-data/ccp_BD.dat,sha256=f00776fnI484B-mzW0rY22KNkzV6wtmk7uxrSK_x9bU,636
|
| 153 |
+
babel/locale-data/ccp_IN.dat,sha256=jMJimrQrx-b96hBSLi8sOyHtYRwNZryt-he0rhwEZ2s,659
|
| 154 |
+
babel/locale-data/ce.dat,sha256=yuopW5QCq1u8E1Rs0hEOv_y1uvbem_P3lK-_AvU5zLE,135403
|
| 155 |
+
babel/locale-data/ce_RU.dat,sha256=NgNmp1uFnm2MT-s_yx_V8KuW1dSR6_SEWf4NcqrAL9o,653
|
| 156 |
+
babel/locale-data/ceb.dat,sha256=fwgJPAV6TfvyavZUW-9pKeLUacMuH03hCkSkHdIGm8I,100779
|
| 157 |
+
babel/locale-data/ceb_PH.dat,sha256=Z2zXPyNI3Yu3QcGL6lT1nIsl04vDDLFvyd9GeucDtqA,636
|
| 158 |
+
babel/locale-data/cgg.dat,sha256=vgLxp4dDUjKyHy-36IvfaPEy6IiXbDiMKShuEKJuXHU,15621
|
| 159 |
+
babel/locale-data/cgg_UG.dat,sha256=HZBma4MFuX2Q7sk-SOYk5OUkbMXWWr_tEInOqPboNYs,640
|
| 160 |
+
babel/locale-data/cho.dat,sha256=hWEL5XrIWAnqjYSb78iPaj2xh34KDcPYAMc46S7ZLuU,795
|
| 161 |
+
babel/locale-data/cho_US.dat,sha256=T3CacgkE-uKPi0CV7fbcCLTNfdjEco_A50vYciuXGGI,654
|
| 162 |
+
babel/locale-data/chr.dat,sha256=4a6eJjX1JZ-inCk-J8gHJq1QtoK3FpOXhOlQMDbHjwM,187187
|
| 163 |
+
babel/locale-data/chr_US.dat,sha256=wZE2RrJ-5jjUQa1RCJgL7hkXdsU3t91orD-ULDYMXSM,654
|
| 164 |
+
babel/locale-data/cic.dat,sha256=KgrmFl1fudc1tdR_g39YkGR6bcIedQMFnUjh831VIhM,2732
|
| 165 |
+
babel/locale-data/cic_US.dat,sha256=DvW1XJS1hEp_W_5ol0pIECeUb3RqXsyieKVS8J6caJ4,654
|
| 166 |
+
babel/locale-data/ckb.dat,sha256=s6wh2TRjabPo4G64RMoQD_J7FK77RBwsK8R0TH1xytI,35553
|
| 167 |
+
babel/locale-data/ckb_IQ.dat,sha256=Osgu1RAUf2yQpZ-nNBKMxTFJnH32ItLg0kVVzjNfmeo,679
|
| 168 |
+
babel/locale-data/ckb_IR.dat,sha256=6wWzlZWn7oDmGIdnF7UtCfIcUgQ1zvMxtAcEw4bbM-g,1231
|
| 169 |
+
babel/locale-data/co.dat,sha256=NbKZ99wTpG7Y64LnyxTQJIo5SYQaUAOybc68DN6IbUY,12637
|
| 170 |
+
babel/locale-data/co_FR.dat,sha256=DAmwXn4n1mRSsT17-DcU0vdVSI_JfVR8oGOnj7hTFHk,653
|
| 171 |
+
babel/locale-data/cop.dat,sha256=MAhXKI-x0mI10Vlgo35ZvUTsKkyx3yrzVIDMfya68rA,693
|
| 172 |
+
babel/locale-data/cop_EG.dat,sha256=ggMojdy-Ua0lFBG-khgVqDiiyDqP6v8JKJzdp4hv-kU,679
|
| 173 |
+
babel/locale-data/cs.dat,sha256=o7qnhuIqxpPIfD-oyVLsvpmhtRiIOzgJBoMaZvyvPL4,247800
|
| 174 |
+
babel/locale-data/cs_CZ.dat,sha256=keaiqSsGtB_axj8FvdYDOCDmlg2PbQMI6qnW-2mFUTY,653
|
| 175 |
+
babel/locale-data/csw.dat,sha256=a31wJpIkcegvNW9_O8LfIY4-HK0zpLn4MBUEBb9C3PQ,20303
|
| 176 |
+
babel/locale-data/csw_CA.dat,sha256=aWccZHGNU7G4JJdlGRnqyqm0ROubX0rwI9SnH_EhAxU,636
|
| 177 |
+
babel/locale-data/cu.dat,sha256=mlGQkibxBcukKPAJawHruBMuw21x1j42ebTnraxW55w,16865
|
| 178 |
+
babel/locale-data/cu_RU.dat,sha256=GcbqgE8Mlglk5EGGSVcCR-Zb8AmCqHGE8cbmAUSbpdY,653
|
| 179 |
+
babel/locale-data/cv.dat,sha256=BUqS-4RvAuycOlAm_k33eV98VCp5bIUmrWUqjhmsqls,198348
|
| 180 |
+
babel/locale-data/cv_RU.dat,sha256=oVPRtcHzmRmkAy26Bv1jLiWmm0P18ruvHlCQ5F3IFY4,653
|
| 181 |
+
babel/locale-data/cy.dat,sha256=-bN00WqRhdnCL9VdnGgtUtwbmZ7n2r96oZdLuxSP8KM,276313
|
| 182 |
+
babel/locale-data/cy_GB.dat,sha256=dyPULIteKk9gP7lGQiDtsiH5QDqNdlxMdK__2dq90dg,653
|
| 183 |
+
babel/locale-data/da.dat,sha256=Aw20nDcBvnWWpy2IYvg9S8hJVoT-gavJ_LokmwppLL4,171762
|
| 184 |
+
babel/locale-data/da_DK.dat,sha256=qNTw1H8WXsV8qGBHxu6noCUOV3BcoR63ERJF8Xc86Ls,653
|
| 185 |
+
babel/locale-data/da_GL.dat,sha256=9BNeKX1-U4NDr3pBU1ZnCGAasdYZjBMsvpdS5uTf9qs,616
|
| 186 |
+
babel/locale-data/dav.dat,sha256=LBf1uH_Q7632sBVhZgQSrdn5LU2pyIU389h4LircJM4,15690
|
| 187 |
+
babel/locale-data/dav_KE.dat,sha256=MfFFEDT6fib5be-EmziiEF0NAnEV6lXD7svYtHUtmn0,636
|
| 188 |
+
babel/locale-data/de.dat,sha256=l6ABVg2zXPX9Ws9g2-Weve05S46ii0hnbuCViS6mtmA,178630
|
| 189 |
+
babel/locale-data/de_AT.dat,sha256=OhoRvklFcyYUJXplBoK2rAITKRi6r81lwOaixIuffcA,2010
|
| 190 |
+
babel/locale-data/de_BE.dat,sha256=wvdWykhix9Slofcjm2tx2aEhMjffmMLsNrd8709NIR0,653
|
| 191 |
+
babel/locale-data/de_CH.dat,sha256=PH2rDxHA3lpTBkPMCwWjapEDJtgrkHhq2_pAdSKSiXE,4091
|
| 192 |
+
babel/locale-data/de_DE.dat,sha256=SM44YjGlqgh7bKlXvUdt53t9hnCX5o46ujI4IrGPpeI,653
|
| 193 |
+
babel/locale-data/de_IT.dat,sha256=ALPY2QGlR9-kphEk4KggHVS51fQwEDVRd7aHLIiP9fw,1448
|
| 194 |
+
babel/locale-data/de_LI.dat,sha256=FnGRiippDTTFRFswU_4PblQruAuWuPEpa8cGbXPJpbE,1413
|
| 195 |
+
babel/locale-data/de_LU.dat,sha256=QAkvLfyKmZdQVfkk2BbE2AMisK1i7yhRetcApqn4dxA,1067
|
| 196 |
+
babel/locale-data/dje.dat,sha256=6NxQgBas9S5kmjbRcbcuuIIxKaI5_MlfmSUltxJuraY,15530
|
| 197 |
+
babel/locale-data/dje_NE.dat,sha256=lU1vag_HJ4OrbYNYWFXuSdtqLwSlwBbvD6Tg-hl36e4,617
|
| 198 |
+
babel/locale-data/doi.dat,sha256=JrHDjsVlGntLL6qYf9NH52BWAGCSGeGVaHg_rgUiGkM,47442
|
| 199 |
+
babel/locale-data/doi_IN.dat,sha256=-q_oAqvdTizFG1DB_1p8sZVyjbaFFQ_FFPtNCyVn9ZA,659
|
| 200 |
+
babel/locale-data/dsb.dat,sha256=KvZxymKZ5ZbxQ-4gS_uvnNkrYMYn3D-BKz0MGAn5488,203926
|
| 201 |
+
babel/locale-data/dsb_DE.dat,sha256=Z2Dzjx7eXscEBEAb-ymvb1GKP4GVNCt5L4i-BYC_vrE,654
|
| 202 |
+
babel/locale-data/dua.dat,sha256=lmO8ssPF9bIgTU2SM_SzrGWodmsGsmbS485uZNDasq4,4827
|
| 203 |
+
babel/locale-data/dua_CM.dat,sha256=Z3vD8WEr2Wlqqt39anvKXVhz4_yBSm4t5BoAaEz9PgE,636
|
| 204 |
+
babel/locale-data/dv.dat,sha256=-1zCv4GXiRHdWjQk0qXWNPSf4FX4Zp-Ij2jwgz5BsGk,2225
|
| 205 |
+
babel/locale-data/dv_MV.dat,sha256=lvuU5gj3vDykU2ftU1_4Lza-130DB6_ZwylDrdb_GlY,635
|
| 206 |
+
babel/locale-data/dyo.dat,sha256=w71HDmFfCuKN9nUJnuqpHR9DDAmPLkwIu9E0abhYjWM,9854
|
| 207 |
+
babel/locale-data/dyo_SN.dat,sha256=Z6N-NIVcKkx6sFUm8LfN74usyZfgeI6swJL_A_XbBcc,617
|
| 208 |
+
babel/locale-data/dz.dat,sha256=dbPhCcTpoQh6szaBA4TN5eCi3sbG1UBvlQQxtMGHLEU,85026
|
| 209 |
+
babel/locale-data/dz_BT.dat,sha256=KWd6cypWse4XfXbY4BmTlxGjlnRksYNcQYi_iyXluKw,635
|
| 210 |
+
babel/locale-data/ebu.dat,sha256=S8bggVknCbVHw5x9aJQGB9kUBFNcwj9EONHRNtbaWCA,15583
|
| 211 |
+
babel/locale-data/ebu_KE.dat,sha256=GEcGqVmH0WwgP1BCsd9vnSGxGXl8ON4UPTRbyeaNDfw,636
|
| 212 |
+
babel/locale-data/ee.dat,sha256=xJ5vpKJa546rTvKKQI75-HvYmu6VjEedXENlPSeDgCg,88730
|
| 213 |
+
babel/locale-data/ee_GH.dat,sha256=SkQi-aVmtqi3S99DUTLQzZqUE4LrAIWuy25QuZqYAfI,616
|
| 214 |
+
babel/locale-data/ee_TG.dat,sha256=7y8-rDvag7_EQtEObq3fpHaRedVmuEREnQwjktmLwgk,1168
|
| 215 |
+
babel/locale-data/el.dat,sha256=pMPkYRvK3y4IF93Z-127ZF_-_P_QV-_460LgZAHCw9o,247970
|
| 216 |
+
babel/locale-data/el_CY.dat,sha256=POPjzTYMuP7Ijf1S88cAFR0ge9Id_sSRNembKdhk2aE,635
|
| 217 |
+
babel/locale-data/el_GR.dat,sha256=S32Cm-1ENgLL_lDecCDI4qDfyd3wlQ1JbUwOnW1whm8,653
|
| 218 |
+
babel/locale-data/el_POLYTON.dat,sha256=lkcs2uXW6mWXztmsAXnapnSuQ6gkns1WwsVgrg-24Uo,14964
|
| 219 |
+
babel/locale-data/en.dat,sha256=iUuuvOPD3NkEnkY0K6ipYXaJlU_dggEeerU5c1EUQZY,220701
|
| 220 |
+
babel/locale-data/en_001.dat,sha256=1h_YIMaDGBLRbF4L34EAmSTm3ihmKctA2GmzG4loU7E,31616
|
| 221 |
+
babel/locale-data/en_150.dat,sha256=cjKCV1ZLhNY4TvqJF8BXvQR1jVUBFrdjL1RKSnBa0vc,1851
|
| 222 |
+
babel/locale-data/en_AE.dat,sha256=T2jBGVJpPTUgTICdaQnAVjSsYCVkQLfjabyStaPl2CU,4164
|
| 223 |
+
babel/locale-data/en_AG.dat,sha256=POWSM98pRq9k7lqCsxr-MS9PA-zLoOVUKUcI9iXtKq4,654
|
| 224 |
+
babel/locale-data/en_AI.dat,sha256=7iwWKftqPdOdWJ7v94jsre2ZIq2cDpbVGAs_ScBztbs,1206
|
| 225 |
+
babel/locale-data/en_AS.dat,sha256=M-N7v6BuP47wkTFmv5by1w42IQCUiSqKbaVTXtnwF8Q,635
|
| 226 |
+
babel/locale-data/en_AT.dat,sha256=05-bVy1aMFWZlHMBC86A7OVy1zlhJw7hsjyvIOjxE70,1309
|
| 227 |
+
babel/locale-data/en_AU.dat,sha256=4Of5kXCe3oX5qViTn-q1ZD-50JSQ-Ly7xX_b6SFWSbY,19022
|
| 228 |
+
babel/locale-data/en_BB.dat,sha256=J8vppKlBp03jJvVuVp6Z4GMc_N0BukeQ8f8q14y8fwU,635
|
| 229 |
+
babel/locale-data/en_BE.dat,sha256=0JXHgqUIWZYe88FYC97spm2TqyIaNOwDJBt3LBmUF7A,1547
|
| 230 |
+
babel/locale-data/en_BI.dat,sha256=AbdI5FjEqQLOMbBtD3wLW_7AccuOwY9MZUFpMF1uEco,1189
|
| 231 |
+
babel/locale-data/en_BM.dat,sha256=cZE8sxf44ETY6nCxOgbvJN2RhABZrRaP8SjwsbSepuE,654
|
| 232 |
+
babel/locale-data/en_BS.dat,sha256=sGvlF2LPwG5eVA3IuH8-4S5X7BrvQ5LcgZ8gfAkkwwc,752
|
| 233 |
+
babel/locale-data/en_BW.dat,sha256=k5bc9gYBdl_8ZyCelrlS9ZenMzs8cdfl2MxeCnOAr88,2850
|
| 234 |
+
babel/locale-data/en_BZ.dat,sha256=LJsn2M0RWMbxDmGRxs2lk2ZvkgoguwPf7oLBYQydU4A,2979
|
| 235 |
+
babel/locale-data/en_CA.dat,sha256=u9gSGF_MnHeklexjpxBWfDQI-5LREnNkP7hAod_hNoY,37942
|
| 236 |
+
babel/locale-data/en_CC.dat,sha256=34a3Vb57hT2reRvwn0Ud1nXkoYQJoPmaqh1n5qflFdI,1187
|
| 237 |
+
babel/locale-data/en_CH.dat,sha256=Nfkwk2HNOccSH8Co5SWYnFdHWEDEpKNPQ2o9a67vt_k,1866
|
| 238 |
+
babel/locale-data/en_CK.dat,sha256=gvU21BSAugpjE7CT3xnpHML6oRgHPaBoq7W11YbG-1U,1187
|
| 239 |
+
babel/locale-data/en_CM.dat,sha256=r_7Yzep6S0ZOFvk_TORm5Qhi55yjehVQAotaLnn7igQ,1437
|
| 240 |
+
babel/locale-data/en_CX.dat,sha256=lKYbIRS6r-WMUd1ewX7Q4TpX0PBVcsYN7Cs263_xosM,1187
|
| 241 |
+
babel/locale-data/en_CY.dat,sha256=kQZfhQdPfdBeePOngn-4CpA3ZJ7Th-lmZ-jOrBe115o,635
|
| 242 |
+
babel/locale-data/en_CZ.dat,sha256=PNwk-yPyyA7DZbmrwm_Bcrhw1jNmFF8WNWtHMXwdVsk,713
|
| 243 |
+
babel/locale-data/en_DE.dat,sha256=oI3TmMDoQZsGddvDb0fbbwd_LdTeFbFPdFkZhst2q7Y,1027
|
| 244 |
+
babel/locale-data/en_DG.dat,sha256=xtjjxkuFB7I4p3n0f4Evz631RtMQhIzpoYwUzOzICqA,1168
|
| 245 |
+
babel/locale-data/en_DK.dat,sha256=pE7x4MDJvZGFnqQqXMCDWoMV3Ovu2qH-QO2oYNvgL4Y,2425
|
| 246 |
+
babel/locale-data/en_DM.dat,sha256=gbriVhXcdXi5GWmpgWdGB1LUwI2yquuLk1khkzpo1UU,654
|
| 247 |
+
babel/locale-data/en_Dsrt.dat,sha256=16L4-KZ6QNunAmMFJ8bSRppOC16aaHl1rtQN8zOCbbQ,38658
|
| 248 |
+
babel/locale-data/en_Dsrt_US.dat,sha256=p8c_L5tEvzYmacz0tmq58Wsbfp9wMV_PBgz5R_v7I-k,653
|
| 249 |
+
babel/locale-data/en_ER.dat,sha256=U1vYaQVwnVgfmO9l2_GjBnAhHrShbiHU_E-hAclDvck,887
|
| 250 |
+
babel/locale-data/en_ES.dat,sha256=UzffO5tH8bSTRY69w0_Smf0vvOrwID6yIjLHdVUphFo,712
|
| 251 |
+
babel/locale-data/en_FI.dat,sha256=i4gKdljmc9cXO-E1IT6JGmq2JsRRH71sKe3yUmkhIa8,2357
|
| 252 |
+
babel/locale-data/en_FJ.dat,sha256=k-hXekogcQzt00qXdcWODsHbg7Vh9U8Vx84bERd8CHM,672
|
| 253 |
+
babel/locale-data/en_FK.dat,sha256=r6OGl7mX4ep5aeFMlhog6Xr--kDKFEVhDcepSJBYZWw,1210
|
| 254 |
+
babel/locale-data/en_FM.dat,sha256=88mCYM5_VDSYpJ_mV4AStjiDpKAo_1W7GbmKcI9f_sk,616
|
| 255 |
+
babel/locale-data/en_FR.dat,sha256=BTiA_ltFmx1GIjAZJ6bCZ2cuucYc--keQ26NCyLcibI,714
|
| 256 |
+
babel/locale-data/en_GB.dat,sha256=2qd2bKhxJeiwIneKwRmH89UCmnYfBdpOFvL02en-YKU,3440
|
| 257 |
+
babel/locale-data/en_GD.dat,sha256=c2ap41e5x-OY5dEYZ5wD4ByRbEzlx0845R1lPBLnJus,635
|
| 258 |
+
babel/locale-data/en_GG.dat,sha256=qhfvbRdldEA4467X0_8N09HwT1ZRPJJtb7Evpvbbarg,1273
|
| 259 |
+
babel/locale-data/en_GH.dat,sha256=bBpzsHl9QhNAQ7hrUtKb6TwGvZYibXQwXfuJVgLMlZ0,889
|
| 260 |
+
babel/locale-data/en_GI.dat,sha256=veSOVDagnkTwyqxP4u5mOkRG8_W4MCZ5ptMBoGOg9SE,1228
|
| 261 |
+
babel/locale-data/en_GM.dat,sha256=jfHQeiMTDNgnIpx3WZ9hOpCR_LXCYLLrVN4SUakudi8,885
|
| 262 |
+
babel/locale-data/en_GS.dat,sha256=4qjeVJPA9Crph3uHpcywYtsNR8S8ok5l38qtEHsIk10,1168
|
| 263 |
+
babel/locale-data/en_GU.dat,sha256=WDR_uybAkUii6RHT2x62pzCLvX4bMstibEztBvLSuxI,715
|
| 264 |
+
babel/locale-data/en_GY.dat,sha256=TDiVa4YSapsK9rjQN3ATnrj3m267l35pqRLI7r5bLFc,694
|
| 265 |
+
babel/locale-data/en_HK.dat,sha256=meLPc5_3zahna_xycXEf75TrW5_4BHuqMQcMyoo1eYQ,2315
|
| 266 |
+
babel/locale-data/en_HU.dat,sha256=6D4ZyheEpHTHE64XVpU6t8ddSWyYT4Hhfo1HEHzimZ8,713
|
| 267 |
+
babel/locale-data/en_ID.dat,sha256=b8R7owdV-fl30WrUhFz-1YGHiFweaoYs_bBFr9pGhD0,3172
|
| 268 |
+
babel/locale-data/en_IE.dat,sha256=ZNe5XFbdM4UnYu6KaGYHggQqzIVCWwWof5C5ktTsHn4,2094
|
| 269 |
+
babel/locale-data/en_IL.dat,sha256=O4-JPTBiiLezF-iUSDu73id-0VWlSiE0ie8z9qRaxq8,1424
|
| 270 |
+
babel/locale-data/en_IM.dat,sha256=u3JX9jrrsW_G5RQXHsQIGl6ikVduckeldeS_FjKG5Y0,1273
|
| 271 |
+
babel/locale-data/en_IN.dat,sha256=2d4aWIy6Q72ExhZHnku5HKbKmSSavvB7zkflqlBsRQA,14809
|
| 272 |
+
babel/locale-data/en_IO.dat,sha256=TOM0TxdcWcu1wyBXJxsrE-uCIZsbYTCmUkTdfCaOO-E,1168
|
| 273 |
+
babel/locale-data/en_IT.dat,sha256=zp8h2lM7v7DPs_9F1CphO3UVNIYsdf1_8Kj9PPiafoo,712
|
| 274 |
+
babel/locale-data/en_JE.dat,sha256=IxL3Ry70pMOXDbCwU6LZllHXZmg8XHbjocavEWvb9jY,1273
|
| 275 |
+
babel/locale-data/en_JM.dat,sha256=Z9GFZ6aFGEvIEzlbOlA5bBBvxgcxXx6s_7AxPMp2Yg4,1666
|
| 276 |
+
babel/locale-data/en_KE.dat,sha256=oJa3lUdjavkdhkMK_bcnJ08waK9lfIRs8mFkG0JYf-4,1458
|
| 277 |
+
babel/locale-data/en_KI.dat,sha256=3yfkrwv7Yd9yxDNnXz9Sv8ghbDvqczZTAELr3uGNYn0,635
|
| 278 |
+
babel/locale-data/en_KN.dat,sha256=cFebccXOrQo2X1zmHoHYB2vzXynoroYImJTMnK9j3h0,635
|
| 279 |
+
babel/locale-data/en_KY.dat,sha256=slmSWk0IEz_UK7PfHX4KyHlf_iBRfuoOWVuEB0aKaYI,733
|
| 280 |
+
babel/locale-data/en_LC.dat,sha256=jUYdKd248Jkj5XVxXXbvXnfxu4BH_3s4Ld-O67qbPkE,635
|
| 281 |
+
babel/locale-data/en_LR.dat,sha256=ribT8_azFjDC8uzIsOwkGTjfgEiFlSG_wAb_wG1Fmnw,885
|
| 282 |
+
babel/locale-data/en_LS.dat,sha256=2HtV3gUrynDl2mVvqywMfff8VnVjz2ryoNS7D2n5T9c,885
|
| 283 |
+
babel/locale-data/en_MG.dat,sha256=dtMrsBqOpwQExs7dVukbUzWojz_6swx5Ng6OXdKxsSs,1438
|
| 284 |
+
babel/locale-data/en_MH.dat,sha256=NZjQknLyokLgJRNPicAZ55_VoRCATz_WvAxMo_I-HOg,1368
|
| 285 |
+
babel/locale-data/en_MO.dat,sha256=UJVR7td-vlRY_a36ZWbxr_PcK6egIUQSKoky3DeAmEA,830
|
| 286 |
+
babel/locale-data/en_MP.dat,sha256=Sd2vA3CdR_GBw1vQQQBfKIY0asJGsVUwZ6gD-h7Or8o,1349
|
| 287 |
+
babel/locale-data/en_MS.dat,sha256=BXrA3odGnWSeR6404L85ErqMKxTnRCZ16UWL2RpD7TY,1187
|
| 288 |
+
babel/locale-data/en_MT.dat,sha256=sODJaESHndxdT9SYZcnESDA6G6oln6n9NCojeHhKvJg,1990
|
| 289 |
+
babel/locale-data/en_MU.dat,sha256=SefoZho0XzSzzU_Y_-udWPCuRgz8ujdUVkL7hhzZO8Q,1438
|
| 290 |
+
babel/locale-data/en_MV.dat,sha256=Spp5zsOCHzCeZOyUdYqXoqmSoIJ0pxRR3b3nI27jvTs,2034
|
| 291 |
+
babel/locale-data/en_MW.dat,sha256=5d20Ih8j6iwBY545I4nObBWdv9FL37nE-ggfpGeXSVs,886
|
| 292 |
+
babel/locale-data/en_MY.dat,sha256=nUwwM17W9W78nnbXGmrx2zComZQ9Fg_pu3va9wPZzvY,716
|
| 293 |
+
babel/locale-data/en_NA.dat,sha256=-yNAAmx38RoVJt3YRH7Tp1xO9o3GsSVDU6uF_GKhGb0,885
|
| 294 |
+
babel/locale-data/en_NF.dat,sha256=6LqhwHyOnkQA4TNvseuiE1a5Ov7DV3y46CZ0ENcibXE,1187
|
| 295 |
+
babel/locale-data/en_NG.dat,sha256=dvbDZYdlkmhF-IU8M6s2p_kHswy8HhdmR3LLc4EhePI,1439
|
| 296 |
+
babel/locale-data/en_NL.dat,sha256=dDCtXReh9uMfUOVqGWaWjfV1-dLe5_yj-o_HrKZGMeM,1192
|
| 297 |
+
babel/locale-data/en_NO.dat,sha256=7PJnnryBa2El81rK1pzjj1XT6PADpW-P9HnL7bRyKzs,1010
|
| 298 |
+
babel/locale-data/en_NR.dat,sha256=ZiUNBY0c1T3LQP-qGmtuxLW2Jfc-lcVTuWpB2jxfAGI,1187
|
| 299 |
+
babel/locale-data/en_NU.dat,sha256=jU4HXz_3l5k-luPPsjZmZBsdOVB5ZfkN1Xuk5i2pduc,1187
|
| 300 |
+
babel/locale-data/en_NZ.dat,sha256=z_qul-H3zQn0Q_lrrHceySj1m2TQaaJZd3QMXE31CcA,2340
|
| 301 |
+
babel/locale-data/en_PG.dat,sha256=WV6D2yT-4GX6ftbnUkK-ihfNg8Y-ImX1Af56okx8LTA,635
|
| 302 |
+
babel/locale-data/en_PH.dat,sha256=oPz_wDvxfCHBpkBUaZ0RiwtPrLtx-9IigR0TIK1b-IM,635
|
| 303 |
+
babel/locale-data/en_PK.dat,sha256=KS_KXItkhkUULbKd9mHdWD9ok4WjZbVSXhU8e5u8blo,2074
|
| 304 |
+
babel/locale-data/en_PL.dat,sha256=us143U1tPhG6MUHpeixIX-yOMwEilDV-tUaQ1XgsjMQ,1038
|
| 305 |
+
babel/locale-data/en_PN.dat,sha256=qpEWWX0fvhzV6gcX_SHNbJW7E-5FikKwXrQAP9BWmXc,1187
|
| 306 |
+
babel/locale-data/en_PR.dat,sha256=bpAu9yoeKxzQTF5Be7AfXtyE3wax0eP0m-Eu-Cr0jKE,635
|
| 307 |
+
babel/locale-data/en_PT.dat,sha256=D1S2jptkyX0igfFWctmR1yCVruIR7IZaJKevAIrPRS8,1039
|
| 308 |
+
babel/locale-data/en_PW.dat,sha256=--3_iiNqupR9R3ccq5foj9HzkADBEwBYdKE_AxLZD3w,714
|
| 309 |
+
babel/locale-data/en_RO.dat,sha256=5_EIBj1QkBAnG-yAK1C2PVjeJh2a33SjlAaTglysxEc,1020
|
| 310 |
+
babel/locale-data/en_RW.dat,sha256=Et3hOZwaSDECrCzypgYq1QxKxxnB3XYziIeEe_WiY7c,1438
|
| 311 |
+
babel/locale-data/en_SB.dat,sha256=h9TJ69YThzzLGTh49BBEmRBxSiZhZpQrVJif0QglLVs,635
|
| 312 |
+
babel/locale-data/en_SC.dat,sha256=omYtCZBrLl8fHuT6XInezdetV7WqWZVYriJRnlWKbTg,1188
|
| 313 |
+
babel/locale-data/en_SD.dat,sha256=ozd3rV_icr8p2H9V6StOSMkoHBPNBsXsay1GMRWZ1zs,928
|
| 314 |
+
babel/locale-data/en_SE.dat,sha256=96guhEOzGr2Lcbd3xZ4j7HTj-0H0oaGMQIbI9a_5g48,1502
|
| 315 |
+
babel/locale-data/en_SG.dat,sha256=u9U5CLnqs0iJmSnMsPBHF71HQLpFM3siADzZeC7iaJ0,2096
|
| 316 |
+
babel/locale-data/en_SH.dat,sha256=rBm_0zxjHnEVzs_CPCyuz5LpI9isA2S6copUuNbxCcM,1210
|
| 317 |
+
babel/locale-data/en_SI.dat,sha256=kkeEkPnW48iNoiwNZb0KV29DPU0oVNuENTi_Wmp2ALc,1046
|
| 318 |
+
babel/locale-data/en_SK.dat,sha256=r6hAr3NnR-tbXF7eA4QVgwe493o_wH-QzcA4xdlYoRU,1065
|
| 319 |
+
babel/locale-data/en_SL.dat,sha256=4hJLAAnyuEVVQZ13NC7wZ0JYJQ3rvX0SsOAp0OoW7_U,886
|
| 320 |
+
babel/locale-data/en_SS.dat,sha256=C4kpyEFjyKT9-6wt2pGl4125aN0Bp0wpcYBrr62nPOc,908
|
| 321 |
+
babel/locale-data/en_SX.dat,sha256=7vESruRIiaBqWxuSRpIE2U6PgWwJ9mxgbjjH_XAraa0,1190
|
| 322 |
+
babel/locale-data/en_SZ.dat,sha256=A9wkzZ5cFffcEf1FobYRPxR1EAFwqQvqELsqRpNleOg,885
|
| 323 |
+
babel/locale-data/en_Shaw.dat,sha256=wU9fC6w85YCi9jeUFo-zofJuR14QaSehUJxcCOGfQik,4776
|
| 324 |
+
babel/locale-data/en_Shaw_GB.dat,sha256=uAIWlJ5gr_NR6lncmMaBrjXUPhZ33rGsXoHz8hrd_E0,653
|
| 325 |
+
babel/locale-data/en_TC.dat,sha256=UWqEc9zpN3NdS1dymbUv2iGKhLkH65Kk9uNFxdXGnOw,616
|
| 326 |
+
babel/locale-data/en_TK.dat,sha256=qz4RHtHQ6cNjB8xW8_BIHdzW1cEcQuyJfdqFIybXAs0,1187
|
| 327 |
+
babel/locale-data/en_TO.dat,sha256=OehJQf8kvWi7A-Rwo2hPjs1Z9pTdg7_Hyx_ewWxbLQ8,636
|
| 328 |
+
babel/locale-data/en_TT.dat,sha256=L23iDn_zvh16iPE5uBlLCRvECSozqyzU9W2OcSjYogE,654
|
| 329 |
+
babel/locale-data/en_TV.dat,sha256=3sj3NCjQg-9UOdTz7wDJRpjx57bI0bntpmx0T50OK9E,1187
|
| 330 |
+
babel/locale-data/en_TZ.dat,sha256=5Q87mjSEaCMmWeWwtesb9lJw2tIWOsvyScG1CqSpWvs,1439
|
| 331 |
+
babel/locale-data/en_UG.dat,sha256=aQLfdbfozsYhK3EG9JXVxsmT4B7UvfSzNBo7kO2WSsc,1462
|
| 332 |
+
babel/locale-data/en_UM.dat,sha256=qd26Sl5bJTEgHU25hvskp4LMxvRJByLOSvUikqz0J4I,653
|
| 333 |
+
babel/locale-data/en_US.dat,sha256=p8c_L5tEvzYmacz0tmq58Wsbfp9wMV_PBgz5R_v7I-k,653
|
| 334 |
+
babel/locale-data/en_US_POSIX.dat,sha256=U8r77o6qQID3Sd5FiZqukSpQnq4LV1BDwHUeuNZjW10,1321
|
| 335 |
+
babel/locale-data/en_VC.dat,sha256=ES4c4Xt6OvJDhxoAZpWR2HFbtyENOl9CrV7XFCBs-MY,635
|
| 336 |
+
babel/locale-data/en_VG.dat,sha256=sqiVUOEtDV2pAc5DzGl76qV1mL5K-UWhMRzG-Ff6r30,616
|
| 337 |
+
babel/locale-data/en_VI.dat,sha256=AGffygfBAafQMxKAAoxt6kwmbES4R_ybbXRV2tHpy04,653
|
| 338 |
+
babel/locale-data/en_VU.dat,sha256=ji2cRB8B-c8uJR7L56HzbkiTR8eJZziVTMcEzuiK2g0,636
|
| 339 |
+
babel/locale-data/en_WS.dat,sha256=gowKsveED3UIWyLgnSWxyE6qq87lH2dMgOVLDGCEcBk,656
|
| 340 |
+
babel/locale-data/en_ZA.dat,sha256=uoSLsVWiMu6x-DYwISGhEwveg0kVsDwgnIhq2Jn0hXo,3411
|
| 341 |
+
babel/locale-data/en_ZM.dat,sha256=8y814a5GtYcC5gvh3YBlcYf5Imr0yNEIV_v8jH3SXqk,885
|
| 342 |
+
babel/locale-data/en_ZW.dat,sha256=GUDDEesQRkUuLyyDlnJ3MGlGzG-kDPxt8OTIqVRKDyw,3320
|
| 343 |
+
babel/locale-data/eo.dat,sha256=kSIbuCrTJF0ZuNV8FzhyheJT33iKwteIHLaYgdfPO4I,101326
|
| 344 |
+
babel/locale-data/eo_001.dat,sha256=3-tP9zaTDfbBBjpd2qKVIhS7WWbmtVKGGW_BmGIhrHQ,850
|
| 345 |
+
babel/locale-data/es.dat,sha256=c62rMW3rHT7taFSTKPt8je50jtFex4sL8nvuVey9224,191377
|
| 346 |
+
babel/locale-data/es_419.dat,sha256=s-JLmJhGKoIbnsjZm-6UXnDsAsgFhIKk9OJk7SPR_oI,27973
|
| 347 |
+
babel/locale-data/es_AR.dat,sha256=rFeyqcUDLb3yYYWMuCP8R4O1n4rT1XCeayaIaoPaOPY,7087
|
| 348 |
+
babel/locale-data/es_BO.dat,sha256=9zgEUshMb69M3LZS_3TOk4kGOt73fnB2UWWR7HPFAgk,1477
|
| 349 |
+
babel/locale-data/es_BR.dat,sha256=oCD_7IoQ5w-C-YXpQ_wBcS0wUkcY268QDcg5y7Vo7KU,1207
|
| 350 |
+
babel/locale-data/es_BZ.dat,sha256=Z3ZskA42UBcpOPDI66F6YBTvzt-g61PmxhiEpdGXpwA,1206
|
| 351 |
+
babel/locale-data/es_CL.dat,sha256=tpiiCMc68Ab3YYDqi_zh0dw_IfsZmLciylujbf72XqQ,4848
|
| 352 |
+
babel/locale-data/es_CO.dat,sha256=_ZNmqQnEj8EoNse4lJuK0Qrg1ZnPSgUVCPCNo7K6FE4,7436
|
| 353 |
+
babel/locale-data/es_CR.dat,sha256=GknsR2O3LbFhHagGvUvgNgBVCVbXZxk-yzivTPR-Q_0,1308
|
| 354 |
+
babel/locale-data/es_CU.dat,sha256=N-TqpCs34sjlEMeJgvrfOSpmnnlGxuuGtSBSaUKDbvg,656
|
| 355 |
+
babel/locale-data/es_DO.dat,sha256=HMY1U9RiyiBlQKc_kUERQ-GHqWCgjaqrBY0mKUE9Gp4,2700
|
| 356 |
+
babel/locale-data/es_EA.dat,sha256=V4UU6BM3pjbuEleLA_MaJtWl8IejNcHzUM660pfKa80,616
|
| 357 |
+
babel/locale-data/es_EC.dat,sha256=i6oUe_5GL6b8ZnbnORW1csbq1-qgo6VN0Z6x9G2xIWk,2941
|
| 358 |
+
babel/locale-data/es_ES.dat,sha256=fd1TSjdlf2lSMxwi0NhYGR2eyiABBaSJvhLlwLO46j0,653
|
| 359 |
+
babel/locale-data/es_GQ.dat,sha256=a7A-hqM9wNt51_CdpjzU8aT9KEeMz165-MyhkWyqJOM,638
|
| 360 |
+
babel/locale-data/es_GT.dat,sha256=zk_WqHmzYsoIAiErSYC9G62MlbgAuySSTAPZLtOX__c,4132
|
| 361 |
+
babel/locale-data/es_HN.dat,sha256=71FLaDfVW5pgllY-BoQoPaDjJ4lvhs_Fi9EBmJQjZj0,3051
|
| 362 |
+
babel/locale-data/es_IC.dat,sha256=hwey8h4GM8i25i-YZR_K-jvCij95wZqr0zdTIKauP58,616
|
| 363 |
+
babel/locale-data/es_MX.dat,sha256=6jxhdWleuQwI_O1FZOl2I5DEwUs3oXjAhJhyBmBCMGM,25204
|
| 364 |
+
babel/locale-data/es_NI.dat,sha256=cF62A52GuQD-QU9-jBmK_8AJ5pZ1W_nJ7NwraSAhMvA,1227
|
| 365 |
+
babel/locale-data/es_PA.dat,sha256=fBNNQGv937Iu4OPHxSuYtPu8M-u6xhUmG0LtMbxDC0E,2775
|
| 366 |
+
babel/locale-data/es_PE.dat,sha256=G6ZcerCUvlSGQmeysFNtMNJEZwPAerVqwOG2hHUpZ_U,7244
|
| 367 |
+
babel/locale-data/es_PH.dat,sha256=fEMZmVPQb97bBjEtCVMLn9JUtosTePmRuQqhpfNYkZQ,1248
|
| 368 |
+
babel/locale-data/es_PR.dat,sha256=wPOPeV-O9rnLzNHObqs9JEUo2ouyqmaiXqtsxHtKpWM,3307
|
| 369 |
+
babel/locale-data/es_PY.dat,sha256=KXiw-rkQCdcoeTv0t0SnA8ioZrHQYfPxen8491aSq80,4442
|
| 370 |
+
babel/locale-data/es_SV.dat,sha256=JM9uw_EVtB6J8bH_Nz0GL_yr6ehay4uAPm4OJIiUmfw,1260
|
| 371 |
+
babel/locale-data/es_US.dat,sha256=ifZ5PL9mZhnqv3E6uRoRS2Sqlkgyz53m2RJs9wDcpMY,22533
|
| 372 |
+
babel/locale-data/es_UY.dat,sha256=31KdHVEWnE6fWuHa7KOdTLcmlWXn8M5liZZMDWlaVrk,2703
|
| 373 |
+
babel/locale-data/es_VE.dat,sha256=kyxdQ51DhLNf6dQauAPw4vOlpjftw9CQgc3yH_uAoKc,2509
|
| 374 |
+
babel/locale-data/et.dat,sha256=eTq6nG039wKW81vnFtx-qzaWVo0wiUey2Y2ZUQLl49k,175652
|
| 375 |
+
babel/locale-data/et_EE.dat,sha256=JpcyzIDpGwHlLSiInuYO3HfxkMEFsDPBeMc-B8Rj3MM,653
|
| 376 |
+
babel/locale-data/eu.dat,sha256=lEQD4nzng6_Fmu8zQtkrvoFWV5AvUaCpOaAlv7vknt4,178023
|
| 377 |
+
babel/locale-data/eu_ES.dat,sha256=ABS9lrwjRkWenVB4fNrwKpr0mOuMF_eOlOrSrobcDl4,653
|
| 378 |
+
babel/locale-data/ewo.dat,sha256=tHyC9Uj5Gkz_nGEiTCFjXn3veej5z1GUhr-j-Dl2vgE,16881
|
| 379 |
+
babel/locale-data/ewo_CM.dat,sha256=likxlZJqzYOVxcG4oSUQLTiH5DjGjdAFsJPIjnnj2Iw,636
|
| 380 |
+
babel/locale-data/fa.dat,sha256=ci_F95dki3wTXhl10yqZP7IomDg1FHIOArxqTEMUEyk,192269
|
| 381 |
+
babel/locale-data/fa_AF.dat,sha256=3lXNqz0r7fjXSYzqZBKGD5gtS0cPs-lx1ExY_s1ucfk,8639
|
| 382 |
+
babel/locale-data/fa_IR.dat,sha256=nPuexwzRHDb9TFMjILK_V43sVIzbcn_fgp0msY3eFQ8,678
|
| 383 |
+
babel/locale-data/ff.dat,sha256=gT8MoHYFJcGDoVjBCYPzsrkMTKylOjXkE64Sc0L-rvM,15911
|
| 384 |
+
babel/locale-data/ff_Adlm.dat,sha256=GbwYyVBbA8SAJP-1BYMW4b3HXivgi8HvRDzIaKuJtvg,326252
|
| 385 |
+
babel/locale-data/ff_Adlm_BF.dat,sha256=eYQLbHvxtEqcJCMbXSkqN2dRSuYHVc6Tg9kOUKayJQs,637
|
| 386 |
+
babel/locale-data/ff_Adlm_CM.dat,sha256=b3VqkcWqXc7s1hCxN60dd-yBRXkcXfMMQ0uAJKmSsg8,656
|
| 387 |
+
babel/locale-data/ff_Adlm_GH.dat,sha256=r1CRe9Z8kZ3B3PDxmZQbvgpsEcY3OjJek9Z_S8FBb5Y,1236
|
| 388 |
+
babel/locale-data/ff_Adlm_GM.dat,sha256=ZM17aBc8xznEjoP4f7HRCHaKn-DIxCSDGkL6GvDYvDw,1232
|
| 389 |
+
babel/locale-data/ff_Adlm_GN.dat,sha256=HWkLsTj8Sd0fWYuYysHhShl08hg0iAvSXhPjy-rUjB0,616
|
| 390 |
+
babel/locale-data/ff_Adlm_GW.dat,sha256=vIUl_C4PZSWmypeEmnsAUbGN2dSquM3nEOdBs22_qNE,637
|
| 391 |
+
babel/locale-data/ff_Adlm_LR.dat,sha256=277rY6zAWlxetFe0D0JpVEY9MNcQiJU9kt1jRoiXE7g,1232
|
| 392 |
+
babel/locale-data/ff_Adlm_MR.dat,sha256=qz618w1XY_zwZ27nB6LBgbzsjsh4UinfnuOVx2bqLgk,1233
|
| 393 |
+
babel/locale-data/ff_Adlm_NE.dat,sha256=waY1EIQKuOkVzrtJ-t-5VY7cK2uKL0SIBO0PQbx4x9Y,637
|
| 394 |
+
babel/locale-data/ff_Adlm_NG.dat,sha256=9UdHELj5G90YopBKktxDyWVQyLxl5f7P3ToBElwlvCo,658
|
| 395 |
+
babel/locale-data/ff_Adlm_SL.dat,sha256=7jLKofwQBRggP61keprrbfFGXvrcJPIOvwEVmUNjcTI,1233
|
| 396 |
+
babel/locale-data/ff_Adlm_SN.dat,sha256=nGazz6Tun3D-XsO6SljxQeeBuzvAb1sBQw21IbkDQKo,637
|
| 397 |
+
babel/locale-data/ff_Latn.dat,sha256=APyNmlFYRwCQOlboY58qsqiF57rrI3F4fHu-uQTdt4g,866
|
| 398 |
+
babel/locale-data/ff_Latn_BF.dat,sha256=Nym5keR3dDPMJBFr7ZyW2cuuY-qTMkdHzXnIHSmfD4Y,616
|
| 399 |
+
babel/locale-data/ff_Latn_CM.dat,sha256=rWaVAF6D5gv_hDhNmSGbcWGpPV7X4gp53FBMXyMjT-8,635
|
| 400 |
+
babel/locale-data/ff_Latn_GH.dat,sha256=-kMvFNIQyikTD2dFakV81ghSR2H584AigLgtmrzlhN8,1231
|
| 401 |
+
babel/locale-data/ff_Latn_GM.dat,sha256=1Air8sk0wb0McqLZXDWIYQeiKgPusBaVjr4zk54IaoU,1227
|
| 402 |
+
babel/locale-data/ff_Latn_GN.dat,sha256=7R-6dXYMBdveo2-9Vc7CjIA2H6y_hGJVbfVGIaJUgbI,636
|
| 403 |
+
babel/locale-data/ff_Latn_GW.dat,sha256=2kbqhzcDeSPQxefHxynmrv2tmFVnWdRNjO7I3AZ6lxk,616
|
| 404 |
+
babel/locale-data/ff_Latn_LR.dat,sha256=MQxcDQnMZC5hN52abzqCjVIL9Z5mA9wOyTqGPP4Oj0g,1227
|
| 405 |
+
babel/locale-data/ff_Latn_MR.dat,sha256=CDUb5owq0Ntsd2lIZJejvYxOjl-NOUPP-v3tgVj1_qU,1228
|
| 406 |
+
babel/locale-data/ff_Latn_NE.dat,sha256=R8C0fI8ql5XpnT29CrwBG8rgdHB1AASDBSdvqIqIQ1o,616
|
| 407 |
+
babel/locale-data/ff_Latn_NG.dat,sha256=00rtiYbJD_ci8-0M4ye95rzGpbyX8qQ-dmFFIajAtRQ,637
|
| 408 |
+
babel/locale-data/ff_Latn_SL.dat,sha256=UaWOeokdbSoxG0JUyyGWkDyz70sXy-cZbc3lXZxmQK0,1228
|
| 409 |
+
babel/locale-data/ff_Latn_SN.dat,sha256=mPVac9iCnwNay8c7Ko3uUvg48lfyfEZrvhpyEFFGmFk,616
|
| 410 |
+
babel/locale-data/fi.dat,sha256=yr9FhmvZuEh0-H8Kx-8XWi-7Suo0K-esRZVVhXdMPxQ,204853
|
| 411 |
+
babel/locale-data/fi_FI.dat,sha256=cpbJU4KKG8OWbmLnc9TKTdzmpoi2AJh_Pu1cHhDwVSM,653
|
| 412 |
+
babel/locale-data/fil.dat,sha256=g0INTCXppDgjTGgBHy9hqQ8Mcw7G9K3XLTLyVshWuuA,144724
|
| 413 |
+
babel/locale-data/fil_PH.dat,sha256=JjoZt3zNxy1X6RnHoxUKOMzT-xMh3tGZBRq8cvrBwqA,636
|
| 414 |
+
babel/locale-data/fo.dat,sha256=4P7HQxbB7uhYUyAt1rFID1mHXUe9zlQBvWCt8LDRhNM,148411
|
| 415 |
+
babel/locale-data/fo_DK.dat,sha256=HUuarLNFSsV_gN2fg-OqrPr-6Ry6KFgitCp173jxAOM,674
|
| 416 |
+
babel/locale-data/fo_FO.dat,sha256=SLeNQ33QTZ92kXCzQcFfo-OgwZVFPJKIeRivuvz0zo8,653
|
| 417 |
+
babel/locale-data/fr.dat,sha256=HvPCR3ft-_VxUpJsVp1wKU8aiJ7eCKZEz9XZVlM5jek,213357
|
| 418 |
+
babel/locale-data/fr_BE.dat,sha256=ODfkJC5kWWEEkjr1UV8AaLtKKc4sPCUxlIGkEDkTr6s,1085
|
| 419 |
+
babel/locale-data/fr_BF.dat,sha256=7piWVeMMrZ-YbO9MNqJAu7ZeIdueVnhg07eeMwJHy94,616
|
| 420 |
+
babel/locale-data/fr_BI.dat,sha256=R4kaU1OtMcNIcibkw8OFGP6FaYMxt2uKMRyidkEqbiA,637
|
| 421 |
+
babel/locale-data/fr_BJ.dat,sha256=sel3fdwegY5W4NRg32t4MuXoqpGqTAGO_ffCF2NPggE,616
|
| 422 |
+
babel/locale-data/fr_BL.dat,sha256=n-MRZjeHNkRMwCtGgPZq52Lj0ijntBsxfskC324i2k4,616
|
| 423 |
+
babel/locale-data/fr_CA.dat,sha256=Nu60QdYyJaiQnz1EbBLSWIO86Rf57q3FWoU7ywZMKQ4,72420
|
| 424 |
+
babel/locale-data/fr_CD.dat,sha256=HWaY-wrLseHcf0fGlRkAWt118iQjRZaTGlqs7G23ZrU,1138
|
| 425 |
+
babel/locale-data/fr_CF.dat,sha256=wxzk0Nf6_pKO2VDivQprUY9WvaxRSkrfQBoUE1UVrAA,616
|
| 426 |
+
babel/locale-data/fr_CG.dat,sha256=zP3HTP-nqZjG-OD_DLrDEPPbB3t9g4T2kHVzI-HxhaU,616
|
| 427 |
+
babel/locale-data/fr_CH.dat,sha256=DiO5jczUyCwTWpWSoxVHE6kLMXQPru-XotJQLDInjKw,2876
|
| 428 |
+
babel/locale-data/fr_CI.dat,sha256=TrHL8hQRuJI3Auxe3aTHYa_rljyUvT_s0q-jdSJflJM,616
|
| 429 |
+
babel/locale-data/fr_CM.dat,sha256=31oDAmeRb3F8a4fvVn1QJyIbrla04w8kfC4oQO0vwkk,1970
|
| 430 |
+
babel/locale-data/fr_DJ.dat,sha256=Jqu2FOJQD41B6fLSBEc_Wf-dIQ-B6MWlT0m1buQnmxo,1248
|
| 431 |
+
babel/locale-data/fr_DZ.dat,sha256=uOe9lbjO51q30G0UMs5nKrMLta5CtLW2Fg4dvsfRX3M,1290
|
| 432 |
+
babel/locale-data/fr_FR.dat,sha256=bwtjtv0NG-lxlXO7fJd6r--l38WKaQmqlmn7PpXJdJs,653
|
| 433 |
+
babel/locale-data/fr_GA.dat,sha256=rMwS-msXjMO5T5k1BP2B2S9B_dYvDHlP8HMS-Lq8XU0,616
|
| 434 |
+
babel/locale-data/fr_GF.dat,sha256=x97-H7H0h4_MUTpjMdrkYB790vBvPKKxmnUTu-FOwLg,719
|
| 435 |
+
babel/locale-data/fr_GN.dat,sha256=6KVlBWrF76ZhgyYg47F1TcR8_fbE5Ii2pJzPhmbr3Pk,636
|
| 436 |
+
babel/locale-data/fr_GP.dat,sha256=W99xHjqPQj_NJ1X34ismj8A4xeZcHu_vyqH8tIwXgeI,653
|
| 437 |
+
babel/locale-data/fr_GQ.dat,sha256=Ogf5NI4zMvbVROeIb8F6h1NxJNKOqY4fKU6G2SPJXDk,616
|
| 438 |
+
babel/locale-data/fr_HT.dat,sha256=S2Vvt2b9Wu4dY5Tsd9xxFAx_RLcWXCGf_XeSSQFYbKQ,1836
|
| 439 |
+
babel/locale-data/fr_KM.dat,sha256=ChLpzCyulxYg8Qmm5HK8YkK203GRSUEBNPSl8war7lA,636
|
| 440 |
+
babel/locale-data/fr_LU.dat,sha256=0sYBhn8-9lvfOrU-ZEIbnO5v03qQOQq4wXCKp70b2sw,729
|
| 441 |
+
babel/locale-data/fr_MA.dat,sha256=Um7dK7MvHkPB_h_r0pk47rMFCng1LWFgIekS7cDX9ZE,1098
|
| 442 |
+
babel/locale-data/fr_MC.dat,sha256=IfTCZ89rqHzUxdKyIz86Zs_VUH2zc5JAvntdhyKsNR0,653
|
| 443 |
+
babel/locale-data/fr_MF.dat,sha256=xU0grNJKWgpfArwpLt7vuOpSTSkyPx3o6gFkmZLCxd4,616
|
| 444 |
+
babel/locale-data/fr_MG.dat,sha256=A9zYBbE6gIWuGDPxv92ReIcR49gtIEYaEkCj9ZONHHI,636
|
| 445 |
+
babel/locale-data/fr_ML.dat,sha256=-PoWsHBtnaZisIOqZyaEFmwooRXb2R2xEMe6DYad_sk,1153
|
| 446 |
+
babel/locale-data/fr_MQ.dat,sha256=45qWAev4p2ZaFVky1Qlrw5q907PDfbRJq9q2UACahm8,653
|
| 447 |
+
babel/locale-data/fr_MR.dat,sha256=mVSOABz3cRa1-HEeUKW13sLw1ZR6PmB9h_DPfZsK4Uc,1228
|
| 448 |
+
babel/locale-data/fr_MU.dat,sha256=c4ERuS1GI8h7waxcW6BRtloW7BThLlgqdYTf31Ioh_U,636
|
| 449 |
+
babel/locale-data/fr_NC.dat,sha256=Su2DaGZPnLCaONmgosMYke9kH6dP8xJ8wJF6P5xrJq4,616
|
| 450 |
+
babel/locale-data/fr_NE.dat,sha256=D6ghYGdDXlhaVQ5gAr8wWHxEHYR7mBs0QaiNL5nfxWM,616
|
| 451 |
+
babel/locale-data/fr_PF.dat,sha256=oPN2EBo1hpLjlpDYPB51qEAx_4HNMWG5-Bh9JN6Kal0,616
|
| 452 |
+
babel/locale-data/fr_PM.dat,sha256=gEP6Ay7r-p7uIjOGXP8eCa62yujlTBntENdeNd9KKes,616
|
| 453 |
+
babel/locale-data/fr_RE.dat,sha256=pxNaLi-BUbe3E-Xf5ZXPoeut9NdT0D9OGEgmoSWZEr0,1055
|
| 454 |
+
babel/locale-data/fr_RW.dat,sha256=gP8mpM7gx_X_9NKDm8B9PuTg83jwT5Nn3NOKPpVhi3w,636
|
| 455 |
+
babel/locale-data/fr_SC.dat,sha256=qvz0N08LKCsPCPDZK1NmAhhzmaszBQ8mSlDbAsEwAoI,636
|
| 456 |
+
babel/locale-data/fr_SN.dat,sha256=n6ijBmMl-ztuCLSePI-Q3yIyhzejn7KvRw5ZqjDoXsA,1018
|
| 457 |
+
babel/locale-data/fr_SY.dat,sha256=tpDovgZ3aK7OumRwbntHTknV-tRL_HjcPK1aQINC-x8,1290
|
| 458 |
+
babel/locale-data/fr_TD.dat,sha256=1H47veWKRj_iV9CxHMz7x7tfrL8IYdQaRWhTV455efw,1208
|
| 459 |
+
babel/locale-data/fr_TG.dat,sha256=r_E5Vnj0Kb5CG16ApHFls4UreDeO7-o3uzpQdJjpbRM,616
|
| 460 |
+
babel/locale-data/fr_TN.dat,sha256=hcGRJ2UjuFEFJqb1BDglGsXY8jCEIdM8--OrU3OqRhc,1228
|
| 461 |
+
babel/locale-data/fr_VU.dat,sha256=FYYsiaoM8QZeClMnQzLiLZNXW9hULz-rCgRTYWvrIvs,1228
|
| 462 |
+
babel/locale-data/fr_WF.dat,sha256=jn6VFRw_qpJFxpO-I6C9nhz_wRZ8cV2b2XRBgSzi710,616
|
| 463 |
+
babel/locale-data/fr_YT.dat,sha256=x0WpQCLoqrLY3_nCF7JlcuekkoUtcpE4llC8kRmeRmY,616
|
| 464 |
+
babel/locale-data/frr.dat,sha256=Itmd93DOwAMGcTkWE83BWDS1oXEVckX0EE6mSiOKyoA,102994
|
| 465 |
+
babel/locale-data/frr_DE.dat,sha256=2ohnodzECbJBUTEta36Ts4amZKl2_LDhuD0-Hu5JBo0,654
|
| 466 |
+
babel/locale-data/fur.dat,sha256=pvg46WO2uwbg27leWyWYXkoqYFiaE1u9Txsd_iZJeC8,32441
|
| 467 |
+
babel/locale-data/fur_IT.dat,sha256=PpDH1opUDjndOtvpPadiOtITGyGxKZY0ziEhb-4HKbE,654
|
| 468 |
+
babel/locale-data/fy.dat,sha256=zJce96OaCoG-oKfhQFisyjgVEK3pNVtF9RT-f9h7y1g,108200
|
| 469 |
+
babel/locale-data/fy_NL.dat,sha256=I_M2hFVCAaVAL90yVMloW2eYmzO5C3NZztfEDAes3_I,653
|
| 470 |
+
babel/locale-data/ga.dat,sha256=rx5MLgtNUisB9V7gu0e2dNyCXF2H9KhLVULuYvLNUh0,261523
|
| 471 |
+
babel/locale-data/ga_GB.dat,sha256=NKphVJhmH8egga1dgfO-hSRVFhbxms2JvGMU3ybgj_Q,653
|
| 472 |
+
babel/locale-data/ga_IE.dat,sha256=P948T1Tl4B7kL1T-uxii27q4IWO3yQQ5emTLv7iHvW8,653
|
| 473 |
+
babel/locale-data/gaa.dat,sha256=W9tUKmjglnSUxVlpiGA0clKmagjmzgF1Fwj_UPmg8Ik,33806
|
| 474 |
+
babel/locale-data/gaa_GH.dat,sha256=FF7vo24vzA2ru3t8py246uanyOqyoSkpD65F7KFTXlA,617
|
| 475 |
+
babel/locale-data/gd.dat,sha256=AtSvR97H05LvFNLHpLsb7tOgKYaOjYvWFOLaDDH6xMk,280763
|
| 476 |
+
babel/locale-data/gd_GB.dat,sha256=weaRul21diYZoqLk7SXacBy8GD1bH30cQO6AHejilPM,653
|
| 477 |
+
babel/locale-data/gez.dat,sha256=6gIHA3BFc3-A6-dOq0pc6bqP2ej6kmG9Xvwa0EEhoMo,12743
|
| 478 |
+
babel/locale-data/gez_ER.dat,sha256=MKpSW7Upkpe42Q2mbJStbjtnrW6Kyo8Tg0zXAxnHWqM,638
|
| 479 |
+
babel/locale-data/gez_ET.dat,sha256=93QTSMihpcfFyRhttFplgAcsAhzrPjlbrz5HI4feRSc,636
|
| 480 |
+
babel/locale-data/gl.dat,sha256=N2zvS1gg8f3l6SOLqIIiKCBsbxAcArFclISemEyGx7Y,153642
|
| 481 |
+
babel/locale-data/gl_ES.dat,sha256=us8xWRQnNTO_KC42-FOU2cnLCNl96591qnxZ4exq5Fc,653
|
| 482 |
+
babel/locale-data/gn.dat,sha256=2CbBgzd3kHlm8uIpKVV3yurmEXB_yNUfM2NKTFV95dU,2477
|
| 483 |
+
babel/locale-data/gn_PY.dat,sha256=tArgCo85T_BUNmPc4sXVRz8X5wcHJmBS6XP0r8dPgA0,635
|
| 484 |
+
babel/locale-data/gsw.dat,sha256=TGHS38pKauNWMdFFsCyCJ_9p17aLt14jMA56gxTDBM4,95265
|
| 485 |
+
babel/locale-data/gsw_CH.dat,sha256=fQlRCd1MJ_gI6rcnkrU-lUE7ZM4syRLh-suMRT0DCOk,654
|
| 486 |
+
babel/locale-data/gsw_FR.dat,sha256=vHNQ1q9Zyf6xLfsJpmqpaX1iHerMRt1dsJSPQdQDoTE,654
|
| 487 |
+
babel/locale-data/gsw_LI.dat,sha256=dsg7TA7MECMrbTXC7i7zXIjrEoqrF2jZ_ckGiTMholo,654
|
| 488 |
+
babel/locale-data/gu.dat,sha256=5A_T6q__RzuWdGg9Sfte2wOqRw_Adz-LJMJJzFJ87cg,208242
|
| 489 |
+
babel/locale-data/gu_IN.dat,sha256=shXUMyk4ogB8uJPazALoReGyLqRXSYOeVBVMn313_Y4,658
|
| 490 |
+
babel/locale-data/guz.dat,sha256=491I3x6EkMG0roSEKI3sHxtaweXWNXhXyk4vsG-LzDg,15427
|
| 491 |
+
babel/locale-data/guz_KE.dat,sha256=Uz_x0_YFKJHDkSd46SvuIfO7W0c-uqYnasmmLNib3WU,636
|
| 492 |
+
babel/locale-data/gv.dat,sha256=Ye3v_q7SrnCeiOVw1r7NRcTtUZ3RwOr1ZKs6skxYTos,3960
|
| 493 |
+
babel/locale-data/gv_IM.dat,sha256=bXOsSoV303kSUECHz2xd5HhASRI-XCjqjxnxpk0Bt10,634
|
| 494 |
+
babel/locale-data/ha.dat,sha256=fVfNqCuIXaCTV5E9XNMNVROCwgalJ8f4MKfEvKun3Ao,150526
|
| 495 |
+
babel/locale-data/ha_Arab.dat,sha256=AUoCyyrZDTrf5SEZ2SRizimC11NMSCyonIkMRer1PxY,2197
|
| 496 |
+
babel/locale-data/ha_Arab_NG.dat,sha256=oYJYqTkaDX2p4IJ9j3sEJT49dcVn_f9JyjO0rUJTmAc,616
|
| 497 |
+
babel/locale-data/ha_Arab_SD.dat,sha256=7DD6pzCmpEdjwbTMAbAb_vJey6Qh0tIeSs8LjEpJxBo,678
|
| 498 |
+
babel/locale-data/ha_GH.dat,sha256=Cwfuh0nEMJu4LGZmdOXJHp_5fZRdpTIODJ_Tpd83uPM,1231
|
| 499 |
+
babel/locale-data/ha_NE.dat,sha256=glKzRtSaovyoiyBc-vjFbJ0wNuxfga49w_zeK3ANtvU,616
|
| 500 |
+
babel/locale-data/ha_NG.dat,sha256=oYJYqTkaDX2p4IJ9j3sEJT49dcVn_f9JyjO0rUJTmAc,616
|
| 501 |
+
babel/locale-data/haw.dat,sha256=aNXNxqponTYIxzV21MX0jIzG73qbhbNO6px2WGael6o,10375
|
| 502 |
+
babel/locale-data/haw_US.dat,sha256=W2qJBTNdETpoN-Ue0UYbqyblj-gIbQNOUMr01RwJ2fw,654
|
| 503 |
+
babel/locale-data/he.dat,sha256=o6AACO6FcY_o6bcUuLkcWgbWIT77K8N8BTBDLY0hk7A,217062
|
| 504 |
+
babel/locale-data/he_IL.dat,sha256=KpQ8sod_QOZ94Tr0tfhlATzVVsrqXck6eq7txoQgCbc,678
|
| 505 |
+
babel/locale-data/hi.dat,sha256=-uw13ozTXWlo39eLvIBYrfQxDROzFOdwmI5wXU66n9A,221948
|
| 506 |
+
babel/locale-data/hi_IN.dat,sha256=UMkxSHgYSdX-hPgYa7rOOzft7xtJwcM0m5nTphUe9xM,658
|
| 507 |
+
babel/locale-data/hi_Latn.dat,sha256=Dn0MJdILlsVYU9R5BJFSPGGr1a35jF4k9ebJMKLX69U,30945
|
| 508 |
+
babel/locale-data/hi_Latn_IN.dat,sha256=UMkxSHgYSdX-hPgYa7rOOzft7xtJwcM0m5nTphUe9xM,658
|
| 509 |
+
babel/locale-data/hnj.dat,sha256=ryXdpBMEUzFyZ_u_YiqAK689QOsEuUO_Auyuhty_4jY,2117
|
| 510 |
+
babel/locale-data/hnj_Hmnp.dat,sha256=6GekZXtZVXtGcI_zk6NqXq3WxMnOx83IpRlJOyUws6s,746
|
| 511 |
+
babel/locale-data/hnj_Hmnp_US.dat,sha256=OydEowg2bNVks5nd5ij7ZJqqQT0ztYv4HL1ZZ4gNajw,654
|
| 512 |
+
babel/locale-data/hr.dat,sha256=kdzKpWmyLAIFw7D5DPKG7aHUQjYlM5fctcBLRoHeujg,207636
|
| 513 |
+
babel/locale-data/hr_BA.dat,sha256=E_S8FRdn0yszTWFg9RlqTV5zEwCc7-qtod45Ud8LHyI,1188
|
| 514 |
+
babel/locale-data/hr_HR.dat,sha256=PqaNYKNdTFgfgmeiINdYp2d3q8qpfkCUs1y4ZHmsphA,635
|
| 515 |
+
babel/locale-data/hsb.dat,sha256=w5bDS336hxU-RChl4QgaayXgMgN_VBUh5GJXznPI_Bs,206887
|
| 516 |
+
babel/locale-data/hsb_DE.dat,sha256=_ELT9KBswSqeyiwbcsP9nFY793FE8PQzEu_2w78Amro,654
|
| 517 |
+
babel/locale-data/ht.dat,sha256=WTxEmIzmX4quBNzQMm0nY3afRvD44p7KBr19xZN_t3k,812
|
| 518 |
+
babel/locale-data/ht_HT.dat,sha256=XR94sLQ8B6jF6SPd_4R6GGLmQQZGe8IoGSDnMYNIT9M,616
|
| 519 |
+
babel/locale-data/hu.dat,sha256=dmS-7GInw1eGbifjgMyXc1m1nBg6dK6IOJIDoLb_Epo,147032
|
| 520 |
+
babel/locale-data/hu_HU.dat,sha256=r3RZskHfUdk1Ba226wqBHAoRMXorlh-IkWLlnY_mBTs,653
|
| 521 |
+
babel/locale-data/hy.dat,sha256=R6n2G8QdkkxlAxBgpTK7l-cPhwHg03vIG1pwmWVrCV4,202316
|
| 522 |
+
babel/locale-data/hy_AM.dat,sha256=r1Bb6WWX2QxVlLP5vRVgox0HgoDOosA-h3oYKLeZMIY,635
|
| 523 |
+
babel/locale-data/ia.dat,sha256=Wa4yDTDv9TA2Imo69v_49GqgV8LvQP1iuWGq6LFAMOk,133538
|
| 524 |
+
babel/locale-data/ia_001.dat,sha256=fzAkHPu7PNj2TOl-kQcJLIdlEK6z-KfVFUVcy-YF5Zg,941
|
| 525 |
+
babel/locale-data/id.dat,sha256=CfCCzK3VV98obeH7x1Ueax-xYczfCwextwJ7aetTQ5A,126977
|
| 526 |
+
babel/locale-data/id_ID.dat,sha256=GvwO35RP_Y8vswE60ItYMQa7XUOBXGLk8tvL8kSJkY4,635
|
| 527 |
+
babel/locale-data/ie.dat,sha256=9nzS8srJ9Mze83D7nKqXSlGvjOtu7utOyAJCLaffEm4,77957
|
| 528 |
+
babel/locale-data/ie_EE.dat,sha256=93dmapYNE5HEAfIRwL_HjNV4fpCJhy1CseggbriCXL0,653
|
| 529 |
+
babel/locale-data/ig.dat,sha256=ts_BawFD_ves9B7kX6GAIxwBY8FP4jNmkZidIdAVaDA,78550
|
| 530 |
+
babel/locale-data/ig_NG.dat,sha256=2MR603ed1L8Y_aZhXPk7K7J8bgQPE4xvvpn8R9Jodiw,616
|
| 531 |
+
babel/locale-data/ii.dat,sha256=WBkpukOuFcoryzq0QnHhdafGfad_u9vdJy0JO9vo-iI,7477
|
| 532 |
+
babel/locale-data/ii_CN.dat,sha256=Vr_Oe23kFnz-EDfl7XeDv6GeTY0LSK-VV6UJpzU8yJE,635
|
| 533 |
+
babel/locale-data/io.dat,sha256=laqBHV7QB933VjLibEOmRezXV9StwhKVzKvWp8e62YA,932
|
| 534 |
+
babel/locale-data/io_001.dat,sha256=T6zZvvSVOcdpy3fhXbdPAWmHCvDTluick2U8_hUDu2E,912
|
| 535 |
+
babel/locale-data/is.dat,sha256=r9gnQpf81NqPVskVKUiSGWa6VU3_NXzJcna1Gho28d8,163097
|
| 536 |
+
babel/locale-data/is_IS.dat,sha256=f3tUj_oYhQ6_tGnn8yda4PZfqChiHmcZXo_nMDCtzSQ,653
|
| 537 |
+
babel/locale-data/it.dat,sha256=n8pxKaMuS2ekD7EOSV-3PmVfdzm9NqxF5zA073x5itU,173579
|
| 538 |
+
babel/locale-data/it_CH.dat,sha256=Tvtge1s4BcbCeKJmPBiSbtbf_qv8wrw3Eb4Dc1sF3dE,2942
|
| 539 |
+
babel/locale-data/it_IT.dat,sha256=-e6EK0A6gEd_G4_BHlmd8_caQ-k_JrEemNgdA0czhsQ,653
|
| 540 |
+
babel/locale-data/it_SM.dat,sha256=xjE63TohE8bjkNiOh-BhOkuB9YWpQ0n2rrBMJoAql5E,653
|
| 541 |
+
babel/locale-data/it_VA.dat,sha256=wwsl_eAmNu9m2JPZnpBwFVh4gsk5AM9lSx8UAXhrMlE,653
|
| 542 |
+
babel/locale-data/iu.dat,sha256=vZIG1AsqwcrTA6zfwBeQydVAn5qDQXT8yTK8wvbaVAA,3209
|
| 543 |
+
babel/locale-data/iu_CA.dat,sha256=C449KxuskTW8w7z56Vv602QRYsQ90O0WbazR7VqlDa8,635
|
| 544 |
+
babel/locale-data/iu_Latn.dat,sha256=oYsdWLomYvVJg6kIQIKYOdSGWyrEHftc2U9bZ0sHFD8,904
|
| 545 |
+
babel/locale-data/iu_Latn_CA.dat,sha256=C449KxuskTW8w7z56Vv602QRYsQ90O0WbazR7VqlDa8,635
|
| 546 |
+
babel/locale-data/ja.dat,sha256=86xPBOY1H1e0fLC6g_61R_ipS4QGbB9sXst_JwwdAWo,179695
|
| 547 |
+
babel/locale-data/ja_JP.dat,sha256=o2pbFmlkEZjV7CHE9cYENYVv2kQA8texhNDhEecgQ9w,635
|
| 548 |
+
babel/locale-data/jbo.dat,sha256=2eB9ymOoFb8abB-v7ISAGcAg4HEEMmpuseHIXFgtqkU,1008
|
| 549 |
+
babel/locale-data/jbo_001.dat,sha256=wwLKEXJOwULYD-q92kQdvpiwW2fgis5YcsP2mT4tnT0,746
|
| 550 |
+
babel/locale-data/jgo.dat,sha256=9X63SqWqQ7TK7Z2RKaQwFBP9sMog_4cQN5Sr_KBlyL0,9031
|
| 551 |
+
babel/locale-data/jgo_CM.dat,sha256=1lDyjZLpK6fS6oSpfnVLdYd2IUgGlUQfF53BDdK7TLY,636
|
| 552 |
+
babel/locale-data/jmc.dat,sha256=lRstulkfCj6kDI8VLH_3GS4awAqVsylMU1hvvWH7kJg,15374
|
| 553 |
+
babel/locale-data/jmc_TZ.dat,sha256=fODp_OsVygbH0UoRsx4HHcXrde02bRKc-hy80sDkcK4,617
|
| 554 |
+
babel/locale-data/jv.dat,sha256=SucM3ZDoHXO7PsbOYNLdx0UmQqWUll2i1hDqn-zJY9U,103138
|
| 555 |
+
babel/locale-data/jv_ID.dat,sha256=G3zTSeqWMngemp5lAcghudTcv-i8egZS12P0-T1DNXw,635
|
| 556 |
+
babel/locale-data/ka.dat,sha256=dIskDjc7ZdRZ1rGJIHxOP_47WO_cdjLDx4eltYETbUE,230234
|
| 557 |
+
babel/locale-data/ka_GE.dat,sha256=zzw4NZBk8dsHIBeEzB3Vtf2_1nC4DhqblLoBUXfNHN8,635
|
| 558 |
+
babel/locale-data/kaa.dat,sha256=KjLQ7_UT8pqVmgqy5BXJHe9hbPceKi6AIyefM4_0pYU,17585
|
| 559 |
+
babel/locale-data/kaa_Cyrl.dat,sha256=zW7tFPX2CPo0NwR2o1DCKu8Tsvm-Aef9RAuy6AcaJXs,693
|
| 560 |
+
babel/locale-data/kaa_Cyrl_UZ.dat,sha256=DugGAZvImbUSHvvGmGw0ekXXBj34vEjSkHhSxVXbc-g,636
|
| 561 |
+
babel/locale-data/kaa_Latn.dat,sha256=zW7tFPX2CPo0NwR2o1DCKu8Tsvm-Aef9RAuy6AcaJXs,693
|
| 562 |
+
babel/locale-data/kaa_Latn_UZ.dat,sha256=DugGAZvImbUSHvvGmGw0ekXXBj34vEjSkHhSxVXbc-g,636
|
| 563 |
+
babel/locale-data/kab.dat,sha256=ykLRvdRtHpY8y7JDHOgC03KxAyvAfxzYQUl44CKKr6s,121528
|
| 564 |
+
babel/locale-data/kab_DZ.dat,sha256=v6fd0kyletm1kfN2ibSUh6oddckpLHjPd_qrq6FQpd8,679
|
| 565 |
+
babel/locale-data/kaj.dat,sha256=tKKi4eYHT0zEJLSHi2DefEGyTTu4RCKpnANu7NQhAPg,2696
|
| 566 |
+
babel/locale-data/kaj_NG.dat,sha256=1RODrBAPxCrrlTgfhpdz-VxQkTdjJEJYHaJEsOgQsNk,617
|
| 567 |
+
babel/locale-data/kam.dat,sha256=br3FOMP0rS2tAq1tSXwYq197v2XXHqWtX_TM-39QP1k,15506
|
| 568 |
+
babel/locale-data/kam_KE.dat,sha256=8AQQhHQdaI4rBKXfTivg884XIDfZlbDEQM28KwvB2Og,636
|
| 569 |
+
babel/locale-data/kcg.dat,sha256=dOZR1bP8sPbhD2Mk496Twz8MOivgGQoliuDMAWSO9fY,2549
|
| 570 |
+
babel/locale-data/kcg_NG.dat,sha256=jCObRZa-t9Khgx_M8ps0PLbeit7rPCFtHeCOhtfCnOY,617
|
| 571 |
+
babel/locale-data/kde.dat,sha256=cFVUYeayn6-kMX6PwQQ3J8rpHMql07_V7lSluInC2x8,15810
|
| 572 |
+
babel/locale-data/kde_TZ.dat,sha256=2sfb3gejYM15YtZeRrc0AJgdaJhqgbVJ9c9yF9SlJmg,617
|
| 573 |
+
babel/locale-data/kea.dat,sha256=o2awnBismFEWQemtUPASmZMVLlOkJNDtuD6egmvMatw,76097
|
| 574 |
+
babel/locale-data/kea_CV.dat,sha256=LyzxPE6yP0f9hdD4uvu8CvEp8nmcmRDVuRI8YxBQ5wM,617
|
| 575 |
+
babel/locale-data/ken.dat,sha256=PMrEuqYRQIhbpP2dPowHOL_NKKFpEBd8qNUV_NpZnDw,719
|
| 576 |
+
babel/locale-data/ken_CM.dat,sha256=jNEojAAtQqJMkEq84kxHU5hGOVQCOW_hnGQScxycYMo,636
|
| 577 |
+
babel/locale-data/kgp.dat,sha256=OKx1ZbBdHw75AdzrT-petm32Dj8wJdtUQH_oai7v0qI,184092
|
| 578 |
+
babel/locale-data/kgp_BR.dat,sha256=FNSYAqPhkzoZzholxTydgasgkuw7jgxCfyKDbeRiLt4,636
|
| 579 |
+
babel/locale-data/khq.dat,sha256=OcW4Zprt-WlTePo7DzquB-yS8vwfPqjaijpkrX5l75w,15753
|
| 580 |
+
babel/locale-data/khq_ML.dat,sha256=ViqThOcZTHZBtebV8LJY-DXdWVX5jAR5pdlBrTKws2Q,617
|
| 581 |
+
babel/locale-data/ki.dat,sha256=vffpb6Wy7TN__hZQH1SJYi81AxamhBnEK_XBCiF3OFc,15451
|
| 582 |
+
babel/locale-data/ki_KE.dat,sha256=PNoxhP-WLxW2vH3fS8N9Nuy0tVimMP-ZAaCfLfnfDN0,635
|
| 583 |
+
babel/locale-data/kk.dat,sha256=93jtpKcfiQBRbyeOyJgqETZXGOntosB2nGedgHShM1w,200871
|
| 584 |
+
babel/locale-data/kk_Arab.dat,sha256=TBsZm6iLJ_dw2mNxDdQk95jELZ87mArNl12iktCwKwo,222820
|
| 585 |
+
babel/locale-data/kk_Arab_CN.dat,sha256=HCoaBi32ENdpJx5usXdBR9aR__MHFeKV-wTo_53tQNk,635
|
| 586 |
+
babel/locale-data/kk_Cyrl.dat,sha256=z3n_4vbUD_OcZhi9Tm8vkSu9h4RUgavZ_CFrujFbuWE,1584
|
| 587 |
+
babel/locale-data/kk_Cyrl_KZ.dat,sha256=eaQW7Va1z2L34hs-D9QgrmyvOo4Lpy2uxxvxms6kL4s,635
|
| 588 |
+
babel/locale-data/kk_KZ.dat,sha256=eaQW7Va1z2L34hs-D9QgrmyvOo4Lpy2uxxvxms6kL4s,635
|
| 589 |
+
babel/locale-data/kkj.dat,sha256=IYeF4Uoeb0kfxooFLFcqmdIwGWbWh0MUfBpztTxWFEw,3373
|
| 590 |
+
babel/locale-data/kkj_CM.dat,sha256=gqHwzVPG_Lo3svaIVe0Kfhj4DaKtstOxJJhUGvvpSbI,636
|
| 591 |
+
babel/locale-data/kl.dat,sha256=D8SSjxLZliXOxyTxpC1x7jYbFQn4WbSV3lfotFFt3Jw,47570
|
| 592 |
+
babel/locale-data/kl_GL.dat,sha256=c49k11GtBG8-vExsQNo_d1pFaQm0LYmXl7QcMSTEApA,616
|
| 593 |
+
babel/locale-data/kln.dat,sha256=pldtRERWUhEOA85_zeFJfshpMl6gtgdELjGyNGtJzOo,17427
|
| 594 |
+
babel/locale-data/kln_KE.dat,sha256=ZhkKgZ2lTdWAvWVOJEFlp4ASvjk2hcyTc2_P9s3mykQ,636
|
| 595 |
+
babel/locale-data/km.dat,sha256=TueDML7PuHjlME0Bew9xgkFSFIxBOsJTzpMwyjyvuXs,176653
|
| 596 |
+
babel/locale-data/km_KH.dat,sha256=bnykdq-RYJ0ZwajV5dFBVtM4anVkLjXutFdUxKByQ2o,635
|
| 597 |
+
babel/locale-data/kn.dat,sha256=n0AHHLkpl4FIYeiSCEMDJF9mFr5nCgHcV8HSCOKz8yw,267281
|
| 598 |
+
babel/locale-data/kn_IN.dat,sha256=rx1LJYeAP8xU6MIU3yhHLuije5OQWL_wzz5glztIdi0,658
|
| 599 |
+
babel/locale-data/ko.dat,sha256=tYIinjTM5ZLw-AvWerUR8h4FRQ09LGfoRNyutl2iMLI,154621
|
| 600 |
+
babel/locale-data/ko_CN.dat,sha256=U_q1api28ucaC-ABOBb822CgSq4nywhMN02uS7TCREI,1187
|
| 601 |
+
babel/locale-data/ko_KP.dat,sha256=BCMOKQSzXNnjAUWfZZ8pbFoSDBed9tnnatyqIePNWio,816
|
| 602 |
+
babel/locale-data/ko_KR.dat,sha256=CJqKij0oULIeCIG8McohdnhEsfJxUwmJHOpJY1bLrNY,635
|
| 603 |
+
babel/locale-data/kok.dat,sha256=1pS0SXgetR-9DHtL71PAw2VIRp51a9KfxoSnw3BoxFs,179992
|
| 604 |
+
babel/locale-data/kok_Deva.dat,sha256=EP15THeV74hd5G3DDXlwIHzxQvpECa67TioBGaur3l8,693
|
| 605 |
+
babel/locale-data/kok_Deva_IN.dat,sha256=GiRy8Q6VCULzgIxNPFEZzABKOg13Un-DblBwXnBSeEk,659
|
| 606 |
+
babel/locale-data/kok_Latn.dat,sha256=jVrQX1SeylbWO6B3ana7r9r1sRvMyOvBVwPfyXxB4uM,29867
|
| 607 |
+
babel/locale-data/kok_Latn_IN.dat,sha256=GiRy8Q6VCULzgIxNPFEZzABKOg13Un-DblBwXnBSeEk,659
|
| 608 |
+
babel/locale-data/kpe.dat,sha256=AHR_ZG1p518D4yulM_cs5E58iMsVXKk4Hi6k0V0IDhQ,1331
|
| 609 |
+
babel/locale-data/kpe_GN.dat,sha256=7eabSFmszupn0IlzP6TRg1-7FZS9AB3JdBkDgJtIs64,1210
|
| 610 |
+
babel/locale-data/kpe_LR.dat,sha256=4O2gzHn_orogC0qOiIyIox-JjyA73hEAe_fZ3Fj5tYc,617
|
| 611 |
+
babel/locale-data/ks.dat,sha256=KySSApsfBfxM26TaXsK2gChd3noV1e5l41gUsaC3DA4,111691
|
| 612 |
+
babel/locale-data/ks_Arab.dat,sha256=fzDL_rCiC-BqymPhF6GBX-d5uVkvZCE4e8JS2L8cjRU,850
|
| 613 |
+
babel/locale-data/ks_Arab_IN.dat,sha256=-OE8PBigMDH8zQrxiaffmabm91Mi8-OVdDR2JEK8xPA,658
|
| 614 |
+
babel/locale-data/ks_Deva.dat,sha256=weXN4SV8247g4MW8R7MHXM6sKk1qhf2Wmowls_zowAM,12510
|
| 615 |
+
babel/locale-data/ks_Deva_IN.dat,sha256=-OE8PBigMDH8zQrxiaffmabm91Mi8-OVdDR2JEK8xPA,658
|
| 616 |
+
babel/locale-data/ksb.dat,sha256=vbB4JVStmpZIu9_vi6f9-Dt40sN2wPvF9Y2JzJJ9oEY,15356
|
| 617 |
+
babel/locale-data/ksb_TZ.dat,sha256=PvWBMUhpMhV27zE9BCEJW8oMqRXWK-6VwmSsXZDMTPY,617
|
| 618 |
+
babel/locale-data/ksf.dat,sha256=IIgvqtnlTxMmLSk38JyZe0PA5gLEX86ZDcaVIULp7Zc,15952
|
| 619 |
+
babel/locale-data/ksf_CM.dat,sha256=0OOsuUS0S_AUxUPySFQOZVbPcB3F2I4yzHZm63YypDU,636
|
| 620 |
+
babel/locale-data/ksh.dat,sha256=M6W02xiGUibDW13RIB7psbwMA2wdNYQHz3Bp9XljhZ0,76781
|
| 621 |
+
babel/locale-data/ksh_DE.dat,sha256=EhgYIJQaC3LGiWrcE2sdfUC8LOWJnciWORi_yoRkOvw,654
|
| 622 |
+
babel/locale-data/ku.dat,sha256=beByrhXjB8iRhaNGxkQaxnUckutus3MJ61Pm-Ro8SqU,117087
|
| 623 |
+
babel/locale-data/ku_TR.dat,sha256=LoNyoL-poYXgqejDzB9-zI_0TIJF3amwyzcs6UnHUII,635
|
| 624 |
+
babel/locale-data/kw.dat,sha256=x5JFxfv4DvLd5Xnq5J7JlbcffhYNXwIn5-Jp3Q5QV5A,7242
|
| 625 |
+
babel/locale-data/kw_GB.dat,sha256=ol7LWhJJFNoNkFEjtk4x1PpLkML9UbuVmZAuG47LokY,653
|
| 626 |
+
babel/locale-data/kxv.dat,sha256=AMdZKJIlfkcpSetPdGRHX8LLN0O1s14NAtDzekSi01E,69503
|
| 627 |
+
babel/locale-data/kxv_Deva.dat,sha256=MlejiNswS_LJAemj-vyEyvXc2SyminqNCWbaq3eceKk,86834
|
| 628 |
+
babel/locale-data/kxv_Deva_IN.dat,sha256=Z43Yc1G4Bsmu7KukFfgXfIl1Cq2Rqa7RQQNYygE5Aak,659
|
| 629 |
+
babel/locale-data/kxv_Latn.dat,sha256=XqtuF9yh0tBrDPoRpZj_1Mw-QUqt98klOlgZXh7qPus,693
|
| 630 |
+
babel/locale-data/kxv_Latn_IN.dat,sha256=Z43Yc1G4Bsmu7KukFfgXfIl1Cq2Rqa7RQQNYygE5Aak,659
|
| 631 |
+
babel/locale-data/kxv_Orya.dat,sha256=lsjWswZU3LWmYNE5tLn9cla-WSbdfqAoltC_OvxtR28,85964
|
| 632 |
+
babel/locale-data/kxv_Orya_IN.dat,sha256=Z43Yc1G4Bsmu7KukFfgXfIl1Cq2Rqa7RQQNYygE5Aak,659
|
| 633 |
+
babel/locale-data/kxv_Telu.dat,sha256=rXJrWxHMFrPeheoNt9NvKLzNoGLpNXiHpc4PsuS4tX0,88218
|
| 634 |
+
babel/locale-data/kxv_Telu_IN.dat,sha256=Z43Yc1G4Bsmu7KukFfgXfIl1Cq2Rqa7RQQNYygE5Aak,659
|
| 635 |
+
babel/locale-data/ky.dat,sha256=PAH_ov1xcnJAie5ltB3I_XAUJsrE_8tFwFlOjorRBts,179889
|
| 636 |
+
babel/locale-data/ky_KG.dat,sha256=CdtjRR2iZgfG5pdz13MX-EHTDtN6BdLeZwGCmrZnrkU,635
|
| 637 |
+
babel/locale-data/la.dat,sha256=nJ1hfe-gN1dlNH5qawfkwjv0bNzefm7UCEwnYv1O6ig,33837
|
| 638 |
+
babel/locale-data/la_VA.dat,sha256=dhULocaXyJGitrljd1w688DTmezcmmY8YcoKsT30n34,653
|
| 639 |
+
babel/locale-data/lag.dat,sha256=mtjtyLHLCfoUr4STtBqLXOxLnZ0igugTC9fZiyJZk8E,16281
|
| 640 |
+
babel/locale-data/lag_TZ.dat,sha256=LlfEls8DDvoVp07MYnFdLBPUhkJs2kzwUDk45BZIO-g,617
|
| 641 |
+
babel/locale-data/lb.dat,sha256=lUGm84DfwLgQ3vC0mL_foFf5dSZZKDTIuwCRf5BjgVs,135641
|
| 642 |
+
babel/locale-data/lb_LU.dat,sha256=s0AY2-F7BqA4tMcRPjCfbzbXRbHsKnD6uIQGSkulCT8,653
|
| 643 |
+
babel/locale-data/lg.dat,sha256=LnMo-qAcWHbbAuRmCTz4_nBGHgUx0aojWG7C8TFn__Q,15834
|
| 644 |
+
babel/locale-data/lg_UG.dat,sha256=nyn_HKdBHGkHlbjlDX28L5Z9k59MKFqvmVL3vg222s0,639
|
| 645 |
+
babel/locale-data/lij.dat,sha256=Ic982St82mPMfuQqqLswPtOy8LlglfcLYk_ftIDM65Q,129648
|
| 646 |
+
babel/locale-data/lij_IT.dat,sha256=rtPerU7ltwkHHc7HErfwJfX8TDSCpTHvBzwKBdSt4x4,654
|
| 647 |
+
babel/locale-data/lkt.dat,sha256=U_yXNWWJkqlepaZ9kS-FVOAHQKVmc0vhwgWgFRzXnqc,11180
|
| 648 |
+
babel/locale-data/lkt_US.dat,sha256=ywWg9m80tNjumAxGNrBwYhXhc28rC4OSdyvkdXAKs5Y,654
|
| 649 |
+
babel/locale-data/lld.dat,sha256=2JBQPu8T-cMVqzVOFs0Vz-0hU2RtHMyTvj0F8wPl2EU,95451
|
| 650 |
+
babel/locale-data/lld_IT.dat,sha256=rHSiZg_-Ba6si2LONUCmQ841RxcX2p7V1jDSuwNNBg4,654
|
| 651 |
+
babel/locale-data/lmo.dat,sha256=GYoR98Ap5hosG9bfENEA3sCkR-msF_KvxV2nLydjs9s,1659
|
| 652 |
+
babel/locale-data/lmo_IT.dat,sha256=Xg4Qvye_hPNJLCTwoBuRMAvhtjQb8VlD9SaH_5hVG9s,654
|
| 653 |
+
babel/locale-data/ln.dat,sha256=OHqUbo7M-600CtpOUNqq3B-Tt0_L3c2GgyR2xZhuMmE,23909
|
| 654 |
+
babel/locale-data/ln_AO.dat,sha256=VNcFViSaGw3f92D60Uk7vxQ8i6Q9H1FD6paDpJh-r4M,636
|
| 655 |
+
babel/locale-data/ln_CD.dat,sha256=Ao_lUWuswJgGHhVJYs2_Z8LyN4iqgYsAda8f9UarT6s,616
|
| 656 |
+
babel/locale-data/ln_CF.dat,sha256=g5Jy7ovUkwcn0W5Ov5bu5SBc2iM4SWwUFwtzWzAAb34,616
|
| 657 |
+
babel/locale-data/ln_CG.dat,sha256=jQld0yw63ufWbhlOt81wjf731zZluc2zWc1A65kBlAM,616
|
| 658 |
+
babel/locale-data/lo.dat,sha256=hXtgT4nkqb8h669TsazfIFBsK23QNpcCZbqvb6SXWBo,189363
|
| 659 |
+
babel/locale-data/lo_LA.dat,sha256=gNa7KRGYWI0h0PcHJ35bwnPskILOH-1jLjHCXP85jaU,635
|
| 660 |
+
babel/locale-data/lrc.dat,sha256=GbK-bWw4TlGvGRyM4WxDujkUr7Gdz9k2A__fSelwEdk,13594
|
| 661 |
+
babel/locale-data/lrc_IQ.dat,sha256=cy9DO9oAKI51NMitAb2MTbZoxtaAPzaYVGV0-xd0mGA,1255
|
| 662 |
+
babel/locale-data/lrc_IR.dat,sha256=-ca4EmTX5VAi_5tDfimpevJFb-g8vAjgpe_jkDTDZWQ,679
|
| 663 |
+
babel/locale-data/lt.dat,sha256=1h5TjFvNSuqrE3JntTmnLN9wW69jfkVakAIICcmoVbc,262613
|
| 664 |
+
babel/locale-data/lt_LT.dat,sha256=j8dIQrFc0s77xJ4P-UGiDcaNqZW6CXOEiOh30FemNiY,653
|
| 665 |
+
babel/locale-data/ltg.dat,sha256=qRaChoBWcmkL8As9MgCysSh58BP_F3US65EaA97ZgZQ,2632
|
| 666 |
+
babel/locale-data/ltg_LV.dat,sha256=Gm8suGbSLaNGzzWPjuEKVdEqJH18ABue4htegryH3bw,636
|
| 667 |
+
babel/locale-data/lu.dat,sha256=4TGAGkYbDHz6QAKQHHXoRkl0Wx-0LOiMkTjDgwJq0TU,15331
|
| 668 |
+
babel/locale-data/lu_CD.dat,sha256=K3k0wMpIbjusgPC2W1q2sxyxynx2M78zOLjt4ikcoZA,616
|
| 669 |
+
babel/locale-data/luo.dat,sha256=xJNSb25OVQogO42d-Jy2fR1FzeSfW9Swwt9Wat4EmsA,15201
|
| 670 |
+
babel/locale-data/luo_KE.dat,sha256=jVUd3oO_U7IP6KmvSkVHYNmlCc8_-m2mpJMBaqArSFI,636
|
| 671 |
+
babel/locale-data/luy.dat,sha256=pcTbaSctQyVgVVh4nXoXxMQGZa3Ip7hsfRN096zwEsY,15030
|
| 672 |
+
babel/locale-data/luy_KE.dat,sha256=NVkQAtmDBXUws3KybnM706J3lwUc5fJo-YEjKd1zhiw,636
|
| 673 |
+
babel/locale-data/lv.dat,sha256=s10obHsTYkBF99rADGvkxupv--JkRPQS2aM6sWvbM4A,201861
|
| 674 |
+
babel/locale-data/lv_LV.dat,sha256=oS9W0pdiTNtMTeGOsef2K7Va2O6k-dQEtN02qCaAoFw,635
|
| 675 |
+
babel/locale-data/mai.dat,sha256=Foj4spiHhuOjBZqaXQxZNCWwdCoslwB7KSX6nXQReu8,95488
|
| 676 |
+
babel/locale-data/mai_IN.dat,sha256=DoclpHa5nlHcAflg286ycOjQ6trZP8uHThzcp37Y91E,659
|
| 677 |
+
babel/locale-data/mas.dat,sha256=xxugbgGc3JxvM2GzV1vmKy1buszviy7NtSH-y6GdMZ4,16595
|
| 678 |
+
babel/locale-data/mas_KE.dat,sha256=zH3Le4j03YNsPjt_-GL5RvPG0znnJKQ3ifbLhMZsoYQ,636
|
| 679 |
+
babel/locale-data/mas_TZ.dat,sha256=VyRJlBqV_fukTqSR9Jxr-PujSA7u-MP9aXrJBVJCKiA,638
|
| 680 |
+
babel/locale-data/mdf.dat,sha256=NQH9Yo77oyvxZj_93XIf0e00JDAoI2ydlCSS3klNgwk,2240
|
| 681 |
+
babel/locale-data/mdf_RU.dat,sha256=sVnTxgzU2rEwl7P4d5UY6XOKv1XUCbtkEQO0cu2OlOk,654
|
| 682 |
+
babel/locale-data/mer.dat,sha256=WFl2qQThWrilUbBaN4UJQb97ZrV3uOB4ZTO9kXsjtnQ,15426
|
| 683 |
+
babel/locale-data/mer_KE.dat,sha256=WqDQTsO6BtbROdcj3p3omUZk8XB6HiJrIlCCj_wLPxo,636
|
| 684 |
+
babel/locale-data/mfe.dat,sha256=n5lJPfd4pjC3xmVm123ivVpjg-WAkLQq9YONw1JlpTs,14835
|
| 685 |
+
babel/locale-data/mfe_MU.dat,sha256=MHUOKiQPHuUbhT6hQXJEkpGDvTUyMV4btJTuiLhJQ4k,617
|
| 686 |
+
babel/locale-data/mg.dat,sha256=9PbZhJ2v9RP2XSzwv7bBPTGlSNYJrUUISNkTwdF1Z7g,18776
|
| 687 |
+
babel/locale-data/mg_MG.dat,sha256=uJbGeEzIn4Rh5Bh4hyV-Hs0_qez9KBeOi4hvfC3zkIw,616
|
| 688 |
+
babel/locale-data/mgh.dat,sha256=ezIhzOd-qzUBRud5ZPjbtBBc_mON2HuKGu_okOahCbk,9753
|
| 689 |
+
babel/locale-data/mgh_MZ.dat,sha256=aFZZ41qtARE6CeecCEx99tzW_fp-XfkAc10wpQ5YeGM,636
|
| 690 |
+
babel/locale-data/mgo.dat,sha256=xyRaEmGV6Fw9nVfReQJY7KfgGwdnvQzScLiH0appsLU,3549
|
| 691 |
+
babel/locale-data/mgo_CM.dat,sha256=Nsp33t4abZsKdDmIgB8tb08OsEh-7JXMY_JKCsd61zY,636
|
| 692 |
+
babel/locale-data/mhn.dat,sha256=RpSxxevhvYxyX0dq1RAhIqoREyyPwKjsByXvOhQkAMc,693
|
| 693 |
+
babel/locale-data/mhn_IT.dat,sha256=3UoH_l7yItN5qXKPaq6bWK_CvK_wD68zkxzLrCwxr9A,654
|
| 694 |
+
babel/locale-data/mi.dat,sha256=ZlyyKSUJCtl7z94uIwEFuC6uBGWXOTM8F1TJLiJeSmw,85086
|
| 695 |
+
babel/locale-data/mi_NZ.dat,sha256=RElP_P4F1HDHjSHsdt54vriFcz0TcIeT26pm-_dy-Mk,635
|
| 696 |
+
babel/locale-data/mic.dat,sha256=Sp71dA3ZhTiiPTfk3b0Mm6y6CM0J-mGR0av-psrUGtI,1638
|
| 697 |
+
babel/locale-data/mic_CA.dat,sha256=uZoBvRFux6M40HcGau7E6V0Pyxh45Bxi0SFngOxLWRQ,636
|
| 698 |
+
babel/locale-data/mk.dat,sha256=xVJU-aubw2FQ_THzBUGd5LHR5IU1VjGkPOeRHpU-T98,216606
|
| 699 |
+
babel/locale-data/mk_MK.dat,sha256=qlI1ZtLgyX2fcYS9pnTa8illdSnPmfNXORjws-H93lc,635
|
| 700 |
+
babel/locale-data/ml.dat,sha256=tR0lt2uQuzmsBgXWIuRpz-AzD00S_OrvLc-QkiYAX-U,246736
|
| 701 |
+
babel/locale-data/ml_IN.dat,sha256=VwCnSFs3oh7xo4-nS1HzWj_xICDzG6E-AW0Oxi6Lu08,658
|
| 702 |
+
babel/locale-data/mn.dat,sha256=O3oSpnDd3Pt-dRrwdg1v245S6Iym3SBnZZ3gqOhQW5A,183647
|
| 703 |
+
babel/locale-data/mn_MN.dat,sha256=qhJGIDXSglsa3BYCalsusoyiKgOj7PJ90Yi4ET2-nxc,635
|
| 704 |
+
babel/locale-data/mn_Mong.dat,sha256=zqCuL28Sx1DS8LGqtC2nyTCoEpSFpF0vE3wvBxpHK1o,1726
|
| 705 |
+
babel/locale-data/mn_Mong_CN.dat,sha256=WTF89EShdtBd0Vz62erFwl9KTG-GgEyzjjmKWuJCFH0,635
|
| 706 |
+
babel/locale-data/mn_Mong_MN.dat,sha256=BTah7qfU9QayUb7evUKdF9c4Ptf4NqqO6SUeUql2Bak,12935
|
| 707 |
+
babel/locale-data/mni.dat,sha256=aS_XIOmHRptFT_dTFuxgTvB2cEPKHJVVM_vtURTFo7A,12972
|
| 708 |
+
babel/locale-data/mni_Beng.dat,sha256=7PTKZT_UE3WNiipyGHnn2SDNFNhAcqHhEJ8T0Y3O7gI,693
|
| 709 |
+
babel/locale-data/mni_Beng_IN.dat,sha256=nAW_LfRtJqC6-ehdC8yyszjhibXqMAXPkuaz8POQav8,659
|
| 710 |
+
babel/locale-data/mni_Mtei.dat,sha256=zdzwNyaRIil7lkjEf6ProQX0nwYlc5VF4r4gHNTUVTY,1720
|
| 711 |
+
babel/locale-data/mni_Mtei_IN.dat,sha256=nAW_LfRtJqC6-ehdC8yyszjhibXqMAXPkuaz8POQav8,659
|
| 712 |
+
babel/locale-data/moh.dat,sha256=FuywEiFRXQe1GUv9zPR15KOsZLr1TykmuglinLINTqE,1316
|
| 713 |
+
babel/locale-data/moh_CA.dat,sha256=AXdrS_As8DrrTGs5IHmQwXoEXndFuoWoTGXPXcL4Pk4,636
|
| 714 |
+
babel/locale-data/mr.dat,sha256=UG0FkufUtQ7qvzcK_WENRq6SgPy4zAcviYDQL-NrGY8,234157
|
| 715 |
+
babel/locale-data/mr_IN.dat,sha256=HOu9QR1BLbciqF6BeTfWvD0L5Igwv5HrCWu9y_vNns0,658
|
| 716 |
+
babel/locale-data/ms.dat,sha256=l_YQob4w4jdu0U-Z-eMYK2bPAyU0Xeekar0olT5G21s,114970
|
| 717 |
+
babel/locale-data/ms_Arab.dat,sha256=9zretwvdo_9N3SIxLKsUtDVNZlmh0OhrPDxmtWqw22U,14359
|
| 718 |
+
babel/locale-data/ms_Arab_BN.dat,sha256=vTEKSh0hjyiWJhf503-fwjADvTCN0AqRSzF6muL52JE,1335
|
| 719 |
+
babel/locale-data/ms_Arab_MY.dat,sha256=w6ZZrz3qEmnsLsWtJA8rTohqF1cxctkzSj4WN0XHuHE,635
|
| 720 |
+
babel/locale-data/ms_BN.dat,sha256=vTEKSh0hjyiWJhf503-fwjADvTCN0AqRSzF6muL52JE,1335
|
| 721 |
+
babel/locale-data/ms_ID.dat,sha256=ZPgnDJgiycDHGZnN3Eg7OgZp1jIYtiZzMqm9f3LOtR8,3440
|
| 722 |
+
babel/locale-data/ms_MY.dat,sha256=w6ZZrz3qEmnsLsWtJA8rTohqF1cxctkzSj4WN0XHuHE,635
|
| 723 |
+
babel/locale-data/ms_SG.dat,sha256=jsfNag5WQWdejzh5hayA7_-IbY03MUVPAPDHUJyCZRg,654
|
| 724 |
+
babel/locale-data/mt.dat,sha256=Xx_-as8jJEXOBAgfFX7vE6-2Qex4FWJ5rYW3DlCbu0A,49384
|
| 725 |
+
babel/locale-data/mt_MT.dat,sha256=L5q5LizZQL0-FLj2U-wn2YhkpL3p7ZvjdyAvH1wwUG0,635
|
| 726 |
+
babel/locale-data/mua.dat,sha256=N4zi8XyQdW_TmszNHQyn4zmia-MpCNWx_Vudoaj075Q,15861
|
| 727 |
+
babel/locale-data/mua_CM.dat,sha256=Ib4K67KfndwGsoZDH0ehHA-F7V_SUj7q9VsK2juzaIQ,636
|
| 728 |
+
babel/locale-data/mus.dat,sha256=zPqFwR9oCIJ0mA6evYwT75cWt_QBF-0eDZx1n6fmsDY,2722
|
| 729 |
+
babel/locale-data/mus_US.dat,sha256=xcd4KKUIqBwSefSC0GGSDkvXL46eDWgWolJsGuSf654,654
|
| 730 |
+
babel/locale-data/my.dat,sha256=9crk_2tyVPKBH_YWC_D0h8o1nbHH9k34e414JywM_6E,183534
|
| 731 |
+
babel/locale-data/my_MM.dat,sha256=l53-D5YL-BbmLZYveFV2ISa4NcrSwTfKsRRc41Jd42U,635
|
| 732 |
+
babel/locale-data/myv.dat,sha256=78-9U5eDf3V2q3Mj0MazIxh1n8sjyVjQ1O0Oyt5875M,16828
|
| 733 |
+
babel/locale-data/myv_RU.dat,sha256=sncxwOpjfFkRASKHMP1ytKcjpF4w4GjU_JEVqXv84Tg,654
|
| 734 |
+
babel/locale-data/mzn.dat,sha256=8Y5VGlzCxKXzBP5iFsyflLZSS1x0_3T8sqbwivfU45s,46144
|
| 735 |
+
babel/locale-data/mzn_IR.dat,sha256=fjN1ek2fAzZyzFJpjX_MIc5oFOEqj7LS_SNdBOQS9ZY,679
|
| 736 |
+
babel/locale-data/naq.dat,sha256=N07nsBSSEuNZ4feWvo7b4YWwbgjBwlxG9653O-OlhmI,15797
|
| 737 |
+
babel/locale-data/naq_NA.dat,sha256=e5gAIOo7le-dVOAX_k2OW6gEyVfEUxcYDUJu_MBDY5M,617
|
| 738 |
+
babel/locale-data/nb.dat,sha256=-bGHDSonSEdqfb2PxNC1_3jOHELm3CwV7xzEtpmWZUE,1330
|
| 739 |
+
babel/locale-data/nb_NO.dat,sha256=J1UiN-AG900acMz4p0fBHtXDpS0HD6uGAi7gg9gOrsY,653
|
| 740 |
+
babel/locale-data/nb_SJ.dat,sha256=XcK9_nKriUY_4k09kmgJalGTls-e5-YS-MCPEKLP8vA,634
|
| 741 |
+
babel/locale-data/nd.dat,sha256=ITmP8mLDb63INBKlxe3yCZqRbvL83DrVBkIIAA_YjmA,15730
|
| 742 |
+
babel/locale-data/nd_ZW.dat,sha256=KpZHrPr_0Ru0t9ojSK9ZiqGZ6-rSpvA7cX9C483ocRk,635
|
| 743 |
+
babel/locale-data/nds.dat,sha256=q3dxEsEcdLTOigPQxhEXuaA4U03umMzIBNC4NkFvino,47839
|
| 744 |
+
babel/locale-data/nds_DE.dat,sha256=Qmh5DjX65W58jXXXX3pxfxS_HVTJVavMspBPdph9sfc,654
|
| 745 |
+
babel/locale-data/nds_NL.dat,sha256=E_EO3ylaBjJNThr211Yzefh5DRbkEFFVpbBMXIQ4U1U,654
|
| 746 |
+
babel/locale-data/ne.dat,sha256=5Ob8IUrudfJp6yCzhHkmYC2mkVY1sd10I79pSXzups0,210152
|
| 747 |
+
babel/locale-data/ne_IN.dat,sha256=SFloADZtyb42wygQmrMy7yx-aADGQECZJUey796oqnw,1292
|
| 748 |
+
babel/locale-data/ne_NP.dat,sha256=LGc7Z5TRi0HRNQdY4bqPitV73gzTPWLd_g-6aPyvryc,635
|
| 749 |
+
babel/locale-data/nl.dat,sha256=iGSLuhpd3RP4i7tOj5RU-vJ1KC_Ij6d5npxRBE5HisQ,149984
|
| 750 |
+
babel/locale-data/nl_AW.dat,sha256=HYycPPe5HDhuP_zN89ysXR2AqjIbx_-XB2n0-TUPhxw,638
|
| 751 |
+
babel/locale-data/nl_BE.dat,sha256=xHmyTOK9-rwPAH6fYdlPFZv-xinmTFNRN-LIGxb59HE,1876
|
| 752 |
+
babel/locale-data/nl_BQ.dat,sha256=lZQzrmWsFTpiWwT9l6FakrNoll3QNP3drIMcxFkAy6Y,635
|
| 753 |
+
babel/locale-data/nl_CW.dat,sha256=doEeLSsQVaSocP4jr5LxNrT5luSiG4hkgsMvoYjJBtY,638
|
| 754 |
+
babel/locale-data/nl_NL.dat,sha256=bGo4nyjhqe1VtDHlP5EUmNkBKsViUSiH3h_ikXcPuRo,653
|
| 755 |
+
babel/locale-data/nl_SR.dat,sha256=d-YXA5QA5b2Bh-WhxNTkyKQ4ROhuEg1CeGN5XmzWcZM,696
|
| 756 |
+
babel/locale-data/nl_SX.dat,sha256=ciTQIntv0njAJGIUENzo6stN8yarfh-eBpmEzxmpJbs,638
|
| 757 |
+
babel/locale-data/nmg.dat,sha256=NEWUb0RI43oeWByH9l1FvrLDvVQY6501jviEYmM_CCs,15468
|
| 758 |
+
babel/locale-data/nmg_CM.dat,sha256=0A-cVUgt1l1ITnPRdcgWiQ68ZGqHDYd-k2wSc_nXnMQ,636
|
| 759 |
+
babel/locale-data/nn.dat,sha256=E-Y0lC-8QKCXdc8CC_ZPN3bstsXsM3MD4Lu62XMMq3U,64042
|
| 760 |
+
babel/locale-data/nn_NO.dat,sha256=98eWK3CBq5T_dI4a6dQH2TktRygMH0EnpO1EO7w8lVY,653
|
| 761 |
+
babel/locale-data/nnh.dat,sha256=cWTTqJEXln6pUYON7H4PRrYr_uRWktSzcLGCC8jnTno,3530
|
| 762 |
+
babel/locale-data/nnh_CM.dat,sha256=dt9ZNHX5ZQo-kcyT4-mVRCUiuzL-H2A9e0s0JrHwZts,636
|
| 763 |
+
babel/locale-data/no.dat,sha256=xxkSV9bwDKWKK6dmGIaZGo4snfkON9eJUp3-uvlEC1w,191212
|
| 764 |
+
babel/locale-data/nqo.dat,sha256=VQzcAnkUnAETAL8xosXBsQltlC4yqpSZNMkwtsWPRgI,109412
|
| 765 |
+
babel/locale-data/nqo_GN.dat,sha256=3eOSTBaZM0RNLUDZFr__KTR_9iZoGUFq9M6bhtmHjcU,617
|
| 766 |
+
babel/locale-data/nr.dat,sha256=ZHIIC8BaR5XBmnULOTfmAYzXmqImq5QmELqbFPKKQJo,2167
|
| 767 |
+
babel/locale-data/nr_ZA.dat,sha256=e4_czqcyMye0qthJd2hzn_9inTS8WjjbFOzRJ3wAS24,635
|
| 768 |
+
babel/locale-data/nso.dat,sha256=dsq0mvwg5QK35al0bVwZGUL961EuGS05vlFR5qb4HwM,6470
|
| 769 |
+
babel/locale-data/nso_ZA.dat,sha256=TdOqVTzKNigLD6zOPR7W7QHT-Aw40ylsUE7bmMwgaKY,636
|
| 770 |
+
babel/locale-data/nus.dat,sha256=4G1Wwsq1yWIew4nA-QBo2j8LmbqBTRZ0gCU0LYLUSUk,8215
|
| 771 |
+
babel/locale-data/nus_SS.dat,sha256=Is_mWvnSS7j05Vk9RHcCfyLOdhOeOWRqgXDf8FGNEJQ,617
|
| 772 |
+
babel/locale-data/nv.dat,sha256=7CBom-BDX6Wk2o878hmZ8DBY8QAS8Z99ExdmdVpq-vQ,721
|
| 773 |
+
babel/locale-data/nv_US.dat,sha256=ak7j2GDaOMbAAmXQhfC9PRM8E9h_hJZL3UDqxqjCtoI,653
|
| 774 |
+
babel/locale-data/ny.dat,sha256=XXvyFcRnNcH9KcAH1K7jzS5xLFsXMlXVW3yowhXPIO0,2152
|
| 775 |
+
babel/locale-data/ny_MW.dat,sha256=kyhkcpqgIwSrUcfxve2OS2P9S1AfXItRHmy94K7cQ48,616
|
| 776 |
+
babel/locale-data/nyn.dat,sha256=nVlbaYbL0QCkpVvX2rYYUFRsuI8BOjcReljkcamobSY,15668
|
| 777 |
+
babel/locale-data/nyn_UG.dat,sha256=fEm-RMI6-PvIjbMUoZK68dTaiAmOqH1iDQBn23a6r2w,640
|
| 778 |
+
babel/locale-data/oc.dat,sha256=0GZZe142JNEQ78GP7q1Sq7ZolzkVuvuK-QDCpLu4Z6Y,66841
|
| 779 |
+
babel/locale-data/oc_ES.dat,sha256=H-3UJZkJCacW_BELiE_wXsXSVHp-dfxv59o3Hed8uho,33273
|
| 780 |
+
babel/locale-data/oc_FR.dat,sha256=L80Ivl6dUpQJF4fAY1xaAeCRO9BkN0l6oCr8nRwogsM,653
|
| 781 |
+
babel/locale-data/om.dat,sha256=wbIQO2bCc4PnuCB14zg9Gw9XW3mlv8D_D0C39SMnAnw,67446
|
| 782 |
+
babel/locale-data/om_ET.dat,sha256=v0wHN7iwcuJN-iFgWFPrGdplH6P-0c8B2OEqYOEeb40,635
|
| 783 |
+
babel/locale-data/om_KE.dat,sha256=DZ-2HywpH9NGEronFox-2AprzyoSg0xJAS62LNqZxcQ,1365
|
| 784 |
+
babel/locale-data/or.dat,sha256=bdzcLCC-BRprtZBlm8pvQhvGKe2zTqjQM1JPQZrGapM,226771
|
| 785 |
+
babel/locale-data/or_IN.dat,sha256=ur6a2cCdapMoKd-6KLXR2xAF2YU8xaueeW7UTPL2yLU,658
|
| 786 |
+
babel/locale-data/os.dat,sha256=2ARxbjnZ_WYF6VQTsvXN4epcXlWpkXaVEhUNOJpAv8Q,14821
|
| 787 |
+
babel/locale-data/os_GE.dat,sha256=8NgIdMuGlNow1dXmjW6y4xOis1_3raiXcj_jLBPirpI,635
|
| 788 |
+
babel/locale-data/os_RU.dat,sha256=76MsfCZxiy_RXfhW7Do3Z8q4-jhp1hOXTBIsA6SlA-Q,695
|
| 789 |
+
babel/locale-data/osa.dat,sha256=Ob-cu1978hig_-zOnB-PJW1_496aZ_yT6S7VTFkHoEY,4538
|
| 790 |
+
babel/locale-data/osa_US.dat,sha256=qFfjNw8tVOdprzqK2wBlGH4eNMxDxDQqDDReucJZR-E,654
|
| 791 |
+
babel/locale-data/pa.dat,sha256=pMTu_1agUQqVCaM7VB5fe9wM45MEsfVkDyzkKp6UlUE,202684
|
| 792 |
+
babel/locale-data/pa_Arab.dat,sha256=VBfuWzoA5UdGbWTTG3cPAYL0ApWSup5U9LWBBh4bGUE,3789
|
| 793 |
+
babel/locale-data/pa_Arab_PK.dat,sha256=1Si67Mz8DZfo2D8Ld0b5IlZpvnSMgg4W8_zZLrHrWQ0,635
|
| 794 |
+
babel/locale-data/pa_Guru.dat,sha256=fs7wqdmuGaKQCCwGkT3lRQSKmf1dxG3jyLboZeVtPmE,1276
|
| 795 |
+
babel/locale-data/pa_Guru_IN.dat,sha256=kpz873B1I65nfS3Z5vDLmmGliFVPlPM58sB6jW9nkBY,658
|
| 796 |
+
babel/locale-data/pap.dat,sha256=EzSKg0e-PaX4UNpqi0JTYSjLYwqljGKI-uJLjR1uWhQ,28121
|
| 797 |
+
babel/locale-data/pap_AW.dat,sha256=XZSGzQPijHNf5GjxUjDJQt88iD0ETRdZSTF8gn-1U4M,617
|
| 798 |
+
babel/locale-data/pap_CW.dat,sha256=Mu-gCfh3bv9pzz9RrylMffuphhqgiRaODEZm6TtCpaI,617
|
| 799 |
+
babel/locale-data/pcm.dat,sha256=BPyAoOzA7PpWZ4G9w2NMBzu1JqtXwnZbeCSrLk7j-Qs,161833
|
| 800 |
+
babel/locale-data/pcm_NG.dat,sha256=3gBp38NIuVEbHlKAtQPQXJjT3DKvy7zvUqMAZS6pGzk,617
|
| 801 |
+
babel/locale-data/pis.dat,sha256=aCXK39YyoYqy97wCU2idxYXLL9cC7myCIiJZeKgq-po,1510
|
| 802 |
+
babel/locale-data/pis_SB.dat,sha256=-CDkXv_877c__o56bBeYHAAq2X9CcnKdI65DiE61_M0,617
|
| 803 |
+
babel/locale-data/pl.dat,sha256=zWkc9nD_Ipzoj-nuymRuCLdWD3dG_wQicGQE5NpjSLU,227506
|
| 804 |
+
babel/locale-data/pl_PL.dat,sha256=3s2XpVyaKha_K9MesXKD6sZNGSn1PVRtuz9XYp1xrsg,653
|
| 805 |
+
babel/locale-data/prg.dat,sha256=vsad78h5dkCtaL_Gc-AGmXy3cc6Od1j4WCPGBdX6Tt0,17267
|
| 806 |
+
babel/locale-data/prg_PL.dat,sha256=5jT2Yeek_e_MpGShmy2v-0WWhzQkQ0WsJQlUYfIOcfU,654
|
| 807 |
+
babel/locale-data/ps.dat,sha256=2Yvun7eRlWEkh6Om_QxdW3Hq3AwyYqoM8n0418VjcbU,158607
|
| 808 |
+
babel/locale-data/ps_AF.dat,sha256=sNE6bgx_nV0VWKa8InelUaFYSa3Fpx6byJw0KT4B1o4,678
|
| 809 |
+
babel/locale-data/ps_PK.dat,sha256=ZtzTnH2thc6-J5PbuMOq3lPu57kbqDFxO53s7BSdVSQ,7119
|
| 810 |
+
babel/locale-data/pt.dat,sha256=6Db_e_tQGLJop802pMj8aeNGcuKxa9iKTCZYBNM4crs,183448
|
| 811 |
+
babel/locale-data/pt_AO.dat,sha256=49hMN9AJBDNjcsQw-nl-jY_VKHanO0PGfvd--OxqOxI,1022
|
| 812 |
+
babel/locale-data/pt_BR.dat,sha256=dVKYp9IwRMbjZ_ee-eXFPudSuTRrROvbFzY3dYTYmn0,635
|
| 813 |
+
babel/locale-data/pt_CH.dat,sha256=zAvD0sYytEquwzY8ZRbVCcy7DS2ZzUXofl5qXOixZH4,653
|
| 814 |
+
babel/locale-data/pt_CV.dat,sha256=zOQn8d7--PKrhRUhQ5mPKW1Km6Tyh5JF8hstfxpITzM,1039
|
| 815 |
+
babel/locale-data/pt_GQ.dat,sha256=qI1hvtuSHOev12ips9o3Vy78NJpOMjhkW625M60lqZU,616
|
| 816 |
+
babel/locale-data/pt_GW.dat,sha256=SRxbFDIg9FwEjGjutRI9P1SeLiZBqStwSqPuHBFZwLQ,1002
|
| 817 |
+
babel/locale-data/pt_LU.dat,sha256=z9aq0BTWEnk4lXveNpmi89TKcXN_t6Ud4A_C97uyOuw,672
|
| 818 |
+
babel/locale-data/pt_MO.dat,sha256=shItJIIDrxwlcQhWLhlZG0uhyTlSBDcTag5ivxmb9TA,1635
|
| 819 |
+
babel/locale-data/pt_MZ.dat,sha256=UZ1nkXS9CpiCM1IpOG5XpGK2QqM5mE5lAgRLTGAWl-4,1042
|
| 820 |
+
babel/locale-data/pt_PT.dat,sha256=_H5DG5pOSZR_5gjjycrMBKaOJd_euwJln1pa3MPd1Mg,96277
|
| 821 |
+
babel/locale-data/pt_ST.dat,sha256=Cm2HUxlGtZaz8IXX5Ohms-HYuKgazuBcOZBz5rWOzEU,1022
|
| 822 |
+
babel/locale-data/pt_TL.dat,sha256=CIIDM_Zo0xiu4gXngxYtkYK6ldTNZMRaikSD_sAokMw,1002
|
| 823 |
+
babel/locale-data/qu.dat,sha256=UueUbNLnx5ZwsqJcvzKUTdK5_wKBOmR2haCj0zhd4RQ,93300
|
| 824 |
+
babel/locale-data/qu_BO.dat,sha256=7RUvNrmuLtwqP-qab667GocH_c4gIvpas3dbN1uaGxU,878
|
| 825 |
+
babel/locale-data/qu_EC.dat,sha256=_5V4RYoPb3eCAA7jOCNfB7WZqd9sWP1E0tlF8mGeqFc,837
|
| 826 |
+
babel/locale-data/qu_PE.dat,sha256=Vdd0fcK2dtFgyui3Q9NElHuJ841RI-T5l2UHeBq8MQ8,635
|
| 827 |
+
babel/locale-data/quc.dat,sha256=dIAxk2IuDZhWTj-NKC9PiHBZOnG9ARyANdJZUfoVlJw,775
|
| 828 |
+
babel/locale-data/quc_GT.dat,sha256=8M8KtmnsJiTCaf-Nl5X174Omtyc6a0ri07kysDC3-5Y,636
|
| 829 |
+
babel/locale-data/raj.dat,sha256=qkuyRruXTTQLDgijSA0Equfz19Aqg0p5Mg0heaGKT00,2428
|
| 830 |
+
babel/locale-data/raj_IN.dat,sha256=SS8GPzJu5j6nfXlDoX4NFPN2QScl4M0YNsrFmWklymM,659
|
| 831 |
+
babel/locale-data/rhg.dat,sha256=dHahMWjQ_tUshtlLauqf9b4Y36LNJFGrMBsVmjBzlqQ,4611
|
| 832 |
+
babel/locale-data/rhg_Rohg.dat,sha256=DAOuwC-7uaIuZtrIXvUkYt6YkxqaKpHOma1m0-XTtrI,693
|
| 833 |
+
babel/locale-data/rhg_Rohg_BD.dat,sha256=DcLSBtf_k_f6B102-vbhBOjfzNZjiTDvEUdIOQfVc8M,1212
|
| 834 |
+
babel/locale-data/rhg_Rohg_MM.dat,sha256=HspZzbytcZQ853Jstp-eFEdqSMAD3-shgjrdxY_KQrE,636
|
| 835 |
+
babel/locale-data/rif.dat,sha256=4KtUTy4D-OsLftEaIHU2fw1NUhx0pwJXXie51jI3X10,49902
|
| 836 |
+
babel/locale-data/rif_MA.dat,sha256=Qq7ZdymuPdjHeYDUDGCjMuQBRU7w5qGdgzzZ6wPfN2o,617
|
| 837 |
+
babel/locale-data/rm.dat,sha256=aQ4MmwhjJbBakV6-C-6yjDvN8jvVa8Mk0ovdYgVkR9k,95006
|
| 838 |
+
babel/locale-data/rm_CH.dat,sha256=JHAlYXMD9Vks43cU_gcSEQmqo6pogWPl_R4VMUK2iHI,653
|
| 839 |
+
babel/locale-data/rn.dat,sha256=LwQTzbFINNeIhU5qJsEnh-raxcCDXVMGA6ZL95aU9UE,16241
|
| 840 |
+
babel/locale-data/rn_BI.dat,sha256=r5Cweh7L4EAZK-qTmJuloWc33iXeR4IJUbknrl0XC3g,616
|
| 841 |
+
babel/locale-data/ro.dat,sha256=13UpR66j-nQg4kbgGH4ja6ygDq1k3CCErykEWeeG8yY,200714
|
| 842 |
+
babel/locale-data/ro_MD.dat,sha256=pUZY970zkBSBpVOIA3Ss-6vDJUF3ZCEWYNs4_LXcpAY,2881
|
| 843 |
+
babel/locale-data/ro_RO.dat,sha256=lLYIYWhDUmq1EZ9oV5SETauVa_5uNN5p52dW7XeemRk,635
|
| 844 |
+
babel/locale-data/rof.dat,sha256=Yafgax503CHjHvrc_njDTMVOOD2B36sRvWvDE99geMI,15473
|
| 845 |
+
babel/locale-data/rof_TZ.dat,sha256=I_qwGjqqrcwUR_3UNydHOm_EiiLZYyRV0q-s1qfSSi0,617
|
| 846 |
+
babel/locale-data/root.dat,sha256=QDYvctKQfBJlCMUl24Gf71HIZQq14_V1LcTK-6udwzQ,51999
|
| 847 |
+
babel/locale-data/ru.dat,sha256=8WD_7_Tz0ieaEjXNlFQy8xFSfCwsVf_CUcoHyFfqkgs,305832
|
| 848 |
+
babel/locale-data/ru_BY.dat,sha256=99UlyhoMWnfyhI5ltXGaJkycWLVfJ3FwdxyRm-yr6kM,676
|
| 849 |
+
babel/locale-data/ru_KG.dat,sha256=X-iAT1QuQGhk1mIetpGyWqDlwiBskLfwqrK6ant1XS8,659
|
| 850 |
+
babel/locale-data/ru_KZ.dat,sha256=P1_Gn3esOwDLL8sd8vVYbFA8J7QEsaDAWfZvDsn-WwA,656
|
| 851 |
+
babel/locale-data/ru_MD.dat,sha256=LU12oBwr7MfPTzfs8Dx7uUZVgHin8ybX_oPHrPIJTkw,654
|
| 852 |
+
babel/locale-data/ru_RU.dat,sha256=IVG440mXjphW6iCsKysZCW1Gem_z5_O0lZI6-R3oG_E,653
|
| 853 |
+
babel/locale-data/ru_UA.dat,sha256=WYPDEOUjHl7mtejs302KAURq_ckDn6CFjH-IwmiFF6g,1210
|
| 854 |
+
babel/locale-data/rw.dat,sha256=1KiBkw5N7hioc-ESs0oqgdyOaVdOlsNp1iIz7g3k83E,8418
|
| 855 |
+
babel/locale-data/rw_RW.dat,sha256=tw-gtzH64PeIAmNGeobgUypw7RAyKITeFAcQPGY0MG8,616
|
| 856 |
+
babel/locale-data/rwk.dat,sha256=hCqo5glP1WqFJrEGyW6r3t43NZ7bVHAOGFGDkUzeM3Y,15369
|
| 857 |
+
babel/locale-data/rwk_TZ.dat,sha256=s9duai8NRoHwn8YpQrlMd3VDf6jtQxxcUmu9CIIMzC0,617
|
| 858 |
+
babel/locale-data/sa.dat,sha256=8r4iZXIQ3vnGxlSmOtDhwM-T_iaYN4SXuTSdGh-2JMg,15978
|
| 859 |
+
babel/locale-data/sa_IN.dat,sha256=ABNamoPpYRbO7bK6BGm0tK92kd7su7_OP7Di0wW0zZo,658
|
| 860 |
+
babel/locale-data/sah.dat,sha256=Qlb3HEv5JslfLAkUjLJz_XdRdyLhloQ9uf9q2b_O6jM,39310
|
| 861 |
+
babel/locale-data/sah_RU.dat,sha256=jHlseiwMbtN-IsETeG2dsaIn6OB2kqtAogazMnn0f60,654
|
| 862 |
+
babel/locale-data/saq.dat,sha256=grj85np3tZzXQmLdtYQcu76ynQv5Jq__KIyaDECFIj0,15787
|
| 863 |
+
babel/locale-data/saq_KE.dat,sha256=kN94cJJt8AT0yBRDqUPGoJtMZdOb2e-83NNsq8hmQ64,636
|
| 864 |
+
babel/locale-data/sat.dat,sha256=K_IKB3mSsOkYuYDtbGW3lbGjVk4ctB56WWkJJvE0-mI,66131
|
| 865 |
+
babel/locale-data/sat_Deva.dat,sha256=0EHZ6UcxsVOfi399xQbOkzaH1OU4jkZ10uqmmWnK8VI,1943
|
| 866 |
+
babel/locale-data/sat_Deva_IN.dat,sha256=Bzh9Vmzia_8KLAryt9VqCl9ter9tKxng4b8oFYbYK6I,659
|
| 867 |
+
babel/locale-data/sat_Olck.dat,sha256=mszOmf6B29mFbE6qN6Moy6SfBjwsjaCsbk75dJR245Q,905
|
| 868 |
+
babel/locale-data/sat_Olck_IN.dat,sha256=Bzh9Vmzia_8KLAryt9VqCl9ter9tKxng4b8oFYbYK6I,659
|
| 869 |
+
babel/locale-data/sbp.dat,sha256=1qHxon8_TpGGnLHUBzy5cR1mCEnZmw1EuYz3QLgnT-c,15609
|
| 870 |
+
babel/locale-data/sbp_TZ.dat,sha256=chWs0tZniO53SbtBquTHGS6E4v36tgYL2b3enxHcdCU,617
|
| 871 |
+
babel/locale-data/sc.dat,sha256=ItaljMMLxOEM4DEG_yDNVk8H4AmQrq1xCnDE8AfRDDs,189970
|
| 872 |
+
babel/locale-data/sc_IT.dat,sha256=0G0vL9YXZQLkTmnzJuuygM5ty2Tw5liDg_aWHLvg32k,653
|
| 873 |
+
babel/locale-data/scn.dat,sha256=UKMqekdt_t_Qe_ebhg3eaRsTs37ECpWLEiWSCFjMTLI,70373
|
| 874 |
+
babel/locale-data/scn_IT.dat,sha256=dTXZIHDRhbFDCw02T0wL1iaJ2kfY1ZUzfbvUs4_WKLs,654
|
| 875 |
+
babel/locale-data/sd.dat,sha256=VDMIluqNpBChcALvjd2lGll6sRK6srAF7p2CogEgXlE,154300
|
| 876 |
+
babel/locale-data/sd_Arab.dat,sha256=jgkaYGUhPXll1T7CT68ridccZaERHeZdwUzGoAZBUps,879
|
| 877 |
+
babel/locale-data/sd_Arab_PK.dat,sha256=c3AXdatnrTNDHW_SOh8fNNye4CVey81FnkSXwj7MmcI,635
|
| 878 |
+
babel/locale-data/sd_Deva.dat,sha256=ZZathBrGJyoqspPsHF769J84zQq1y62vN8RAjGj_Cms,13957
|
| 879 |
+
babel/locale-data/sd_Deva_IN.dat,sha256=0KQFEKHV6hHidc5hxrxQEvhO-YyvFf5P5z6t9hPenH4,658
|
| 880 |
+
babel/locale-data/sdh.dat,sha256=5cD8u88qanpCtA8kPvHH9AdAi2-HbhznORqis1PYx6M,1032
|
| 881 |
+
babel/locale-data/sdh_IQ.dat,sha256=B_vUMOiGWVcD1HaR4Zk8XxVzcmMFSISe2vRscyA1lYY,679
|
| 882 |
+
babel/locale-data/sdh_IR.dat,sha256=hwMmQnne41X_lyjbyNbQq34Lpkl91bAgoavPZRuozwU,679
|
| 883 |
+
babel/locale-data/se.dat,sha256=JnN5s3b1OrcP7qmurb8Rb9NKc-ICOr_RmdFs2EBKoRA,54830
|
| 884 |
+
babel/locale-data/se_FI.dat,sha256=9_VJ0wzYFPto0YF2Ge0qieFV9_DOVqqYnPjlC5wnAr8,44207
|
| 885 |
+
babel/locale-data/se_NO.dat,sha256=nm5u2VQ3ne0SUFZtFqwsRa8Gg97Xn1OSxjoP2I-i_PU,653
|
| 886 |
+
babel/locale-data/se_SE.dat,sha256=6M9OxtmQAY_p9fZ_6L8zqo6i--bo_X00cvhTDEbX_UU,694
|
| 887 |
+
babel/locale-data/seh.dat,sha256=viFuK-Mg4wPnvTcrvL-iEzNqFc7Ri_VP_r9pC673SNE,15433
|
| 888 |
+
babel/locale-data/seh_MZ.dat,sha256=Sv94DueqrM3R5RjhCdwrKZsnNdL1WpjLBg6QhBnoaX0,636
|
| 889 |
+
babel/locale-data/ses.dat,sha256=aRW4cH7nGNS5S3B3ff7o02GqcIqn1mVbBRGg3NdxXUc,15812
|
| 890 |
+
babel/locale-data/ses_ML.dat,sha256=y14qGwP_r6VxzJhklYIWfYkolu0OHB-6nJ4tvF7J-iU,617
|
| 891 |
+
babel/locale-data/sg.dat,sha256=ERl6d_xd8JRnkG_D857gWi2xONyI-cEmzt-Un_hXbu4,16476
|
| 892 |
+
babel/locale-data/sg_CF.dat,sha256=QCNYqo_5l2Sv9JUFEWF6YLDR3MknhgkyMz1mO5j2Gv8,616
|
| 893 |
+
babel/locale-data/shi.dat,sha256=fuYtv_xjgmJ0-aAQiuWcJXZY3mpeq__hz4lnouEUyWE,21830
|
| 894 |
+
babel/locale-data/shi_Latn.dat,sha256=aQrfwwcvkgPaWFSev9-3WgwQXhhXj1_5myuR-QifnPo,15435
|
| 895 |
+
babel/locale-data/shi_Latn_MA.dat,sha256=X8cwkkvm2LjcClQWzHRxxmiA8P0c37D7P8lf6RO4iNQ,617
|
| 896 |
+
babel/locale-data/shi_Tfng.dat,sha256=VjsR4oSiK9oFfdIdpaVDwNSIBvFbQ3Jvm63K24bRqk0,974
|
| 897 |
+
babel/locale-data/shi_Tfng_MA.dat,sha256=X8cwkkvm2LjcClQWzHRxxmiA8P0c37D7P8lf6RO4iNQ,617
|
| 898 |
+
babel/locale-data/shn.dat,sha256=awBFmgdlHbpKsnUqWZaGAQ-YbTPm9UWkJKMn9IdJ7pM,890
|
| 899 |
+
babel/locale-data/shn_MM.dat,sha256=7VauV3cmVfAJz7kA76hsF3FdwM75CVjvHdjx6lCoH4M,636
|
| 900 |
+
babel/locale-data/shn_TH.dat,sha256=QHPmr3V4GzTbb6QA5SDl2EsVzQBjpbaDP6OHfJZ0S0Y,636
|
| 901 |
+
babel/locale-data/si.dat,sha256=iuq-0rbecyzhX0pRX5UYdgKKzrn09pkLucKursW_Z94,216775
|
| 902 |
+
babel/locale-data/si_LK.dat,sha256=cWCgV9WmnEwIIsBmhsIVzSzbrV8hkkXaV1xH1ultlUw,635
|
| 903 |
+
babel/locale-data/sid.dat,sha256=zyKwuzw51B0E8sWg60qJ3kO4rzqTtcNBRnH5D3Zm1mU,2176
|
| 904 |
+
babel/locale-data/sid_ET.dat,sha256=vtwy9BuaZwb5A3XdIl-3mws1cEAVk4s8oKy7i-GnM9o,636
|
| 905 |
+
babel/locale-data/sk.dat,sha256=u_TnuG4-zvLxkxQupdNvPS-TYi28xeiPxLit28hxwZM,218242
|
| 906 |
+
babel/locale-data/sk_SK.dat,sha256=eMjPq18mQOAXvkJN5WV6lKEAPyt7-eleGme2pHHevgA,653
|
| 907 |
+
babel/locale-data/skr.dat,sha256=Mrx5bET3kh5Gzd8-2J9Rm4_b_wPZTDoHuhcxqdYj5hA,1702
|
| 908 |
+
babel/locale-data/skr_PK.dat,sha256=UJpLMmJJIM5jeI-tXWPBNX4Qd3WS2nTwp3bvJg5D3WY,636
|
| 909 |
+
babel/locale-data/sl.dat,sha256=eEJU8du-WwCkCviFmusUqH8H6sMl2PHG_khSumUB3co,210137
|
| 910 |
+
babel/locale-data/sl_SI.dat,sha256=3Hk2t-MUfAUtqu_Gy0_fTjOhwBUtxdnndQ7Kowg0qek,635
|
| 911 |
+
babel/locale-data/sma.dat,sha256=BaBVbhsEPN9V4JGtMt2TpMdf0oIrL8Maxt2FXDIEEss,944
|
| 912 |
+
babel/locale-data/sma_NO.dat,sha256=OeIJ-EJtvWH6z2dZ1Hv8QdmQC7M7r51t-_C6LD6ZyxE,654
|
| 913 |
+
babel/locale-data/sma_SE.dat,sha256=M_zYllAUd2UaWvccZ6ShB9-Gd8JYzIEln-88Q23syaU,654
|
| 914 |
+
babel/locale-data/smj.dat,sha256=eyHR5AZqbxxlTYhyxJfvTjpz_v6zfh3TrDtcDkCgTig,939
|
| 915 |
+
babel/locale-data/smj_NO.dat,sha256=5fz-YVJEoXswvC-RdFcJWmt-EMGcNXA3c9j_pfmxqCA,654
|
| 916 |
+
babel/locale-data/smj_SE.dat,sha256=7l73FEZcAemOwXSrfPB3X7a0cto3J4oM7AO9i9PMIBU,654
|
| 917 |
+
babel/locale-data/smn.dat,sha256=LGkyaifqt24L0NeExCtzhg8rKEKnkfJNEKtt67B-ViE,40399
|
| 918 |
+
babel/locale-data/smn_FI.dat,sha256=VRY3dbCyxEmDUTep9bQXDRldd5wSg4skqQpztnMXplk,654
|
| 919 |
+
babel/locale-data/sms.dat,sha256=ylATYbrfu8SVEVdQRbC7dTSOKCNSX7O1gjS2wJXA1tU,6521
|
| 920 |
+
babel/locale-data/sms_FI.dat,sha256=b-Mk20lC32xysqU5v6jGjDUYDZaMDvoMwWOZNdT5yuA,654
|
| 921 |
+
babel/locale-data/sn.dat,sha256=FNTHDspBYVPY7Nse1haEc19O0Sf3btsqNWQFs2Zzcgc,16732
|
| 922 |
+
babel/locale-data/sn_ZW.dat,sha256=8HnH2raHHl8PI25abODlThEhjIOGXJb_u7cyQd5YzZw,635
|
| 923 |
+
babel/locale-data/so.dat,sha256=sAFkgMg-qaZYhHT_lyoaggZ8UM_KX1xbS4miB3l5KN8,166227
|
| 924 |
+
babel/locale-data/so_DJ.dat,sha256=VWnaj_MuW4dJnlO84t60ySCvfJL7FXI4nIP9PTL5Amo,656
|
| 925 |
+
babel/locale-data/so_ET.dat,sha256=EvRRqU4yQPMYhkEK8a4MR808fwKHmW7EvPvEJdjltnE,655
|
| 926 |
+
babel/locale-data/so_KE.dat,sha256=OSiRggRZ7CTNmqiGOvW1W2Cw2RqjVESTVOdUfgVgWyU,1208
|
| 927 |
+
babel/locale-data/so_SO.dat,sha256=2IPbOqSxQGB5FukQ-B-MEme9FHYn22ClXmAV4x08pNE,616
|
| 928 |
+
babel/locale-data/sq.dat,sha256=8lTejyAm-94ixpS6Dly7NQSHNsamftqLIdO4OxPWqok,160229
|
| 929 |
+
babel/locale-data/sq_AL.dat,sha256=MN2RvkKGG2PXjCRsMHsvcnwnIOOp9tNSpcInh2uCWaI,635
|
| 930 |
+
babel/locale-data/sq_MK.dat,sha256=L_GaZJ9XuQMs0zw-xZlrefPF36SH0sJqMrdDDbwicZM,1208
|
| 931 |
+
babel/locale-data/sq_XK.dat,sha256=qILZGRwAhuIBJ9xi_T5WTrrZAVouFjQSvybrwgXTsog,1187
|
| 932 |
+
babel/locale-data/sr.dat,sha256=AAE3LN_CLRWzljEERIYedZepxLIDWzENkL4wmu8Ib6c,265725
|
| 933 |
+
babel/locale-data/sr_Cyrl.dat,sha256=Tbo90CyBAWciKeDesPhmXf7sdBQfjWsmyyrKBco_NzU,1990
|
| 934 |
+
babel/locale-data/sr_Cyrl_BA.dat,sha256=sKEcBX9G9OwCmIZEpTphQyW_LM4xoDGe90s_470_AJs,41992
|
| 935 |
+
babel/locale-data/sr_Cyrl_ME.dat,sha256=rDZOf-zykN151tfgGiO1SUJiClzQ6t40gF927bMLn1I,2320
|
| 936 |
+
babel/locale-data/sr_Cyrl_RS.dat,sha256=Tn9u1EvJAZZEIdgXloi326qjpq8b1N087nRQ9R1JbWE,635
|
| 937 |
+
babel/locale-data/sr_Cyrl_XK.dat,sha256=qVevTILYnuaIjRyPy4rDTavVg-VXxKcZ5fVdh5c-aHQ,1574
|
| 938 |
+
babel/locale-data/sr_Latn.dat,sha256=1joKXYRv5UiiT21s_Za6qE-VA8XpFi1HzYnVOjKpxb8,217950
|
| 939 |
+
babel/locale-data/sr_Latn_BA.dat,sha256=of4wpeCglVK_Td6HnHUjHRwuFtCVtWj3kHb3nl4B0D8,32834
|
| 940 |
+
babel/locale-data/sr_Latn_ME.dat,sha256=Mr0GNVLFIMZpBakd4dEUzJUlAN4nyX2BMAqydgtMzWo,2089
|
| 941 |
+
babel/locale-data/sr_Latn_RS.dat,sha256=Tn9u1EvJAZZEIdgXloi326qjpq8b1N087nRQ9R1JbWE,635
|
| 942 |
+
babel/locale-data/sr_Latn_XK.dat,sha256=wIz7XXQrRFYpzMpR_cgSWikPWI0ehSx5a0gRBgt3rFo,1486
|
| 943 |
+
babel/locale-data/ss.dat,sha256=UAB0p3UMDn8KfBY32a7HVWXWpHlPa26Nr_Woaah2c3U,2178
|
| 944 |
+
babel/locale-data/ss_SZ.dat,sha256=X-Va1uVrsPa1ZX5hwhQ-ME6Q_bovUb24XXFS8UQ87lQ,1208
|
| 945 |
+
babel/locale-data/ss_ZA.dat,sha256=xwT3vZ4tmKEvJpVwFMV9U2j2FLF1tC9PEDN6MC6Qbf4,635
|
| 946 |
+
babel/locale-data/ssy.dat,sha256=QyBWLhH_sreFEBHMQ7aiqBsrGvDeQHyYAKioqksa2iU,2999
|
| 947 |
+
babel/locale-data/ssy_ER.dat,sha256=9CRIaVxgOMeMTc0tcV0Yz9yZzq_uD3g3ylZzqVpYzsM,617
|
| 948 |
+
babel/locale-data/st.dat,sha256=b-jiK03L_9F4QqWW8qmRJ3UZntZDI9eMJglRho3MN7c,8016
|
| 949 |
+
babel/locale-data/st_LS.dat,sha256=pSzdNm6-O5V6-14VcgF2iGNYQPFYIXQlY3SqUW3GcjA,1227
|
| 950 |
+
babel/locale-data/st_ZA.dat,sha256=5tdUX7dxXEL2xiS_0IvHvqhKF-gWXFsi4supkP0RDAc,635
|
| 951 |
+
babel/locale-data/su.dat,sha256=G66EuouIQrCxgKGW9JzPfMZ94NAN87P6REyULyyrFGw,11817
|
| 952 |
+
babel/locale-data/su_Latn.dat,sha256=ievzq_m7eD5pZWLnVlH7oMIdeadf8GIMqEuVPJTBjyM,745
|
| 953 |
+
babel/locale-data/su_Latn_ID.dat,sha256=axNaukDpD_-G-_4R7P1u5w4dh-ToRPN_Yo-QpC1cFRU,635
|
| 954 |
+
babel/locale-data/sv.dat,sha256=RTvQ2li9cKHIEbVl7fI8ENVrmcCa1gERk3S9O2bHKmA,198967
|
| 955 |
+
babel/locale-data/sv_AX.dat,sha256=QFGzIe9UCr5gCpgHunvdPiZ-126vP7GYORL9jjip9-E,653
|
| 956 |
+
babel/locale-data/sv_FI.dat,sha256=Pn3EDh-VD0QJFWupEZ6w4TqAa-WC5GZ8oTA4oqLazvc,2526
|
| 957 |
+
babel/locale-data/sv_SE.dat,sha256=c9PG5p2y_4rnxepGD4uOzemBU3EOQhQNO4BtUS1m3rE,653
|
| 958 |
+
babel/locale-data/sw.dat,sha256=w0uX0MB-_bZQWOnbdyDVg1uRVe1j-K-egjRExoZpE8U,145419
|
| 959 |
+
babel/locale-data/sw_CD.dat,sha256=W7Fw8Wqwo3_x4hWlssmWbVTj4hhSQmRv8c-VSnQdlg8,2577
|
| 960 |
+
babel/locale-data/sw_KE.dat,sha256=YMNWSTJ8qxo0d1KvQwAN5ECRaZ9LGc0BDfX4enggVlc,47036
|
| 961 |
+
babel/locale-data/sw_TZ.dat,sha256=I1bDbpEDiR1jkCgJ_W9fWCPuPxMhjQmwG3sIueKb-Rk,616
|
| 962 |
+
babel/locale-data/sw_UG.dat,sha256=kuNdg2N_dLwUKFm7wSheL1wLOdyrukPxLfDw0PN7tT8,660
|
| 963 |
+
babel/locale-data/syr.dat,sha256=vuGk7MOpvWxjzuHSoG8mAJEKGbI70UoRq-DxlvwqT5c,111105
|
| 964 |
+
babel/locale-data/syr_IQ.dat,sha256=Mrw63eJwh0vRe3Lpj0vRf6Q4cUZXJcx9tlWkuAmMrss,679
|
| 965 |
+
babel/locale-data/syr_SY.dat,sha256=l0Yl2UMjm_7kuzvoG2-KqBp5XR88gdjf1ZlpRRNFMuc,679
|
| 966 |
+
babel/locale-data/szl.dat,sha256=8PpGSXa6ES6yxXD2YOBjG16b6BW9jDZo86RKB0MCNn8,88759
|
| 967 |
+
babel/locale-data/szl_PL.dat,sha256=1D5dKaG2l2Haxde8uraWI2J5lzw1dIWGeJtBesua-IM,654
|
| 968 |
+
babel/locale-data/ta.dat,sha256=RRIrxhZ9pdpGShIrQx7ZQBOPKWn15OGkeL8yQOy-tz8,277264
|
| 969 |
+
babel/locale-data/ta_IN.dat,sha256=BOFaDBw7fc7C6xSSFYNfkhCgCUd7ydHprJ6u0DaneSE,658
|
| 970 |
+
babel/locale-data/ta_LK.dat,sha256=Od6ln5oUnWfaAHwt_SDafWv844c7A7_7fTT2OPVTuyw,1208
|
| 971 |
+
babel/locale-data/ta_MY.dat,sha256=PEUmjhs_RUr1R5kH9uHExdnG59Hy8LmbU18vXZYYPtA,1325
|
| 972 |
+
babel/locale-data/ta_SG.dat,sha256=tbuefTSiXPMwpeV085Qp53l5uDHLsMMXmt8TPEG2fWY,1344
|
| 973 |
+
babel/locale-data/te.dat,sha256=oRTQlv5dIZYav2aQWijvc2wm0VwoR1TwWUPL_qhzkuU,261668
|
| 974 |
+
babel/locale-data/te_IN.dat,sha256=LICnXU-D0uhvxVpQ986Ul1JeAQktXaX53sXZSUY3L2g,658
|
| 975 |
+
babel/locale-data/teo.dat,sha256=jJ-266Aw_zTeJjwGj_VASqzm6Y3CcQYkVPXKuV_kzT8,16012
|
| 976 |
+
babel/locale-data/teo_KE.dat,sha256=S_lAg36VkA1w384kzPfXRLmJmGWfmz3ll7MzOQAtcr8,657
|
| 977 |
+
babel/locale-data/teo_UG.dat,sha256=0WlDglms5bCe1AMwCqroaXpOXu9jQroxllMwXWLb8q0,640
|
| 978 |
+
babel/locale-data/tg.dat,sha256=ErMv0Y4SGno9gTSJbhMVKZXiSe_KNSUFaoBeIDaP8tk,117163
|
| 979 |
+
babel/locale-data/tg_TJ.dat,sha256=TCrsEipGp0reAS2mAvwT58tyzBnYJfL5oNHWpEe1ttc,635
|
| 980 |
+
babel/locale-data/th.dat,sha256=lyG_l3_QzfpnjCv8LVaRTvpvfImkVrqcDoUKrnXlIR4,215576
|
| 981 |
+
babel/locale-data/th_TH.dat,sha256=_QhA0WcHmW6Cr_-gU9e6cdpzTMDT19WyHas58fWDUnc,635
|
| 982 |
+
babel/locale-data/ti.dat,sha256=K4kS476YQonyQifjLpS4UkE7hNa2k5aIDBJRIdh2eDg,214273
|
| 983 |
+
babel/locale-data/ti_ER.dat,sha256=m9w0P5TPQ8IqpWKldwdfnw5_1Upv09AjLdO5WUbcRic,962
|
| 984 |
+
babel/locale-data/ti_ET.dat,sha256=q0b9svPg8aj9xmbXr7F6fPHqeTJmclBl5t_hqQk7IuU,635
|
| 985 |
+
babel/locale-data/tig.dat,sha256=cgqxy3wiehP8yceqa5-mrJVT23IP_bjlkeUOEvxspUM,13481
|
| 986 |
+
babel/locale-data/tig_ER.dat,sha256=OoQ0U6yyzmjKwDtzLUpqR09h_ZaGvzXlp7t-HqNxmm4,617
|
| 987 |
+
babel/locale-data/tk.dat,sha256=z5i4kshTasDEolkNpqXnzlZh75EgbAhL0ylT0_0oioo,164932
|
| 988 |
+
babel/locale-data/tk_TM.dat,sha256=lADxEQoz-_ImDBmpCFUqDPuZ0ozVUhZKOQF2ZwyXVlw,635
|
| 989 |
+
babel/locale-data/tn.dat,sha256=LgoZgcUCS4t_RsyQQKiVsJ7Kbs7HoInZAMndRk6DUCM,8596
|
| 990 |
+
babel/locale-data/tn_BW.dat,sha256=jWMFP1tw-o7rslHAlAIgjEXflko8UCDNaSuQ8ccvNHI,654
|
| 991 |
+
babel/locale-data/tn_ZA.dat,sha256=S3dMOsYSpBwkUv0tW9q0kKawQQl6yx77LexAL5wQqDU,635
|
| 992 |
+
babel/locale-data/to.dat,sha256=CBr6gRgu0qo_-kIoOluPwu_ZdH4-SPPJHto_ERcDzHA,145255
|
| 993 |
+
babel/locale-data/to_TO.dat,sha256=jcfJ2Pjof8jGE4q1y5LHSP9rb4IanN58kR7OgG8d5Q0,616
|
| 994 |
+
babel/locale-data/tok.dat,sha256=kuSPgVhnv8Rr55G-epQDVyh8FfeKxJbd2J0hierJdUQ,8870
|
| 995 |
+
babel/locale-data/tok_001.dat,sha256=PPUMevT2TBOGFSq-U-AccYkLHSbkWnBRDvxtpokTCD4,693
|
| 996 |
+
babel/locale-data/tpi.dat,sha256=mqTAJweAOy1SAH2l4mJAKktX-ZeAdvTC8JnBPxXjB0A,4030
|
| 997 |
+
babel/locale-data/tpi_PG.dat,sha256=uZD_c8yCtiYwt2EO2VOYPzhSTqWMQBOJMCuMCXe3Css,617
|
| 998 |
+
babel/locale-data/tr.dat,sha256=ULbjOvmQqcT1Z2_8bBOe7LzwgBUg3LWM2MiLkmb8M6w,150824
|
| 999 |
+
babel/locale-data/tr_CY.dat,sha256=3EmCqxcPvFuZcHCzpTmHb6pjtPwqQvwCfn27B8rtXNw,1227
|
| 1000 |
+
babel/locale-data/tr_TR.dat,sha256=7lS5CMZw76SVlMJxsmIJW5IfL7k9t8MrfKcnElqISSI,635
|
| 1001 |
+
babel/locale-data/trv.dat,sha256=iEbFtCCE_U5rmjAv0Pe5J_UigixMKq1cPIThdZui1Lg,9404
|
| 1002 |
+
babel/locale-data/trv_TW.dat,sha256=CTQtGdDW4Z0n2Ckb6B63HgEwNE44YTFnJCetwd8q9GU,636
|
| 1003 |
+
babel/locale-data/trw.dat,sha256=1e1LGCtVq79RclEMJbgRE4ATdqflV_KDHxBwInSfAKc,110107
|
| 1004 |
+
babel/locale-data/trw_PK.dat,sha256=pBHdOulrwRLiQuC96g8ilUzpKBeG6kglBqUXB8MlURA,636
|
| 1005 |
+
babel/locale-data/ts.dat,sha256=p7EFPucK9HkTVXeNKTU00s-Oas5U_HCPGX9hqT15p9I,5522
|
| 1006 |
+
babel/locale-data/ts_ZA.dat,sha256=AByEO55W3DVVOBIBxIp1F2QwY01-5v6v8sDFOGSxCF0,635
|
| 1007 |
+
babel/locale-data/tt.dat,sha256=X-J0BKEHy01aoARwwb0SWDuNm1lZFrT0akKrzBZjHPM,111014
|
| 1008 |
+
babel/locale-data/tt_RU.dat,sha256=cmv2MzolKOrsRoqQcFZGcXQj_33dLWGh9oUjnebCnz0,653
|
| 1009 |
+
babel/locale-data/twq.dat,sha256=nOSN5UZAxcCgdTxQFh14Cyk5K38olCyAuT6MrVW5PeE,15509
|
| 1010 |
+
babel/locale-data/twq_NE.dat,sha256=y8xQDxMtyStWC83tm_JiekFxAY0Fj-CWWdmic9GBwd4,617
|
| 1011 |
+
babel/locale-data/tyv.dat,sha256=y90_CH7Yksd1Kuc6KhykhpkdGVLUgFDV-B4oSxGqn5E,693
|
| 1012 |
+
babel/locale-data/tyv_RU.dat,sha256=vP_6cjMLB8I8YL7Nqrq4Gu_AWGFuANbZSdBc7ORn_IA,654
|
| 1013 |
+
babel/locale-data/tzm.dat,sha256=wYFO2vX38bht1nAdcVA7dxKVMh-3yC5sItggFaXkKBo,15436
|
| 1014 |
+
babel/locale-data/tzm_MA.dat,sha256=8eku_7voAqAjN651VYKCuIWvdYGOScCyqbt1rtSVO_g,617
|
| 1015 |
+
babel/locale-data/ug.dat,sha256=jRJJxRRKuYljj6kYicIhxWk8ySzpMT9AOePaBk3EO94,117801
|
| 1016 |
+
babel/locale-data/ug_CN.dat,sha256=2UselU1_d6K7NgQj0EDnDfb4Llk51eQZ7z78oYE-Ywg,635
|
| 1017 |
+
babel/locale-data/uk.dat,sha256=b8iEhvLdQxq7rtlqpx1c9vp6-n3jNGPGSuBWNhZAnFA,339125
|
| 1018 |
+
babel/locale-data/uk_UA.dat,sha256=usJw_J4Uu9OD9nrUxNQAx6vMJBWDjbGuc9l7ssJAyuw,635
|
| 1019 |
+
babel/locale-data/ur.dat,sha256=RTL85URWDMA3albZQODUCbVTA9oxeYXo5kWtuL1XW6g,167002
|
| 1020 |
+
babel/locale-data/ur_IN.dat,sha256=9GV9YIa7Mftq14Po2C6fjMG5sWkU8J5LS5bq1iIcsHg,10550
|
| 1021 |
+
babel/locale-data/ur_PK.dat,sha256=EEAGl6fLd1-a7X0n2PwRxlqwYZ0a0ELm2DuLII9spX0,635
|
| 1022 |
+
babel/locale-data/uz.dat,sha256=iwj3ukxb4FK0rZYtC66ftQmTtr1SgTzy12Wu3KkQYQo,138052
|
| 1023 |
+
babel/locale-data/uz_Arab.dat,sha256=wt8BwimSNmoFzrnduGDXMHhqj3B8-XqqN6ghg2Xm74A,3814
|
| 1024 |
+
babel/locale-data/uz_Arab_AF.dat,sha256=68eUCR8KeB0QDQRCvNMiOIkZVRozGKFTDednrQL1X_Y,678
|
| 1025 |
+
babel/locale-data/uz_Cyrl.dat,sha256=RpmyW2YhTwN_o6sKyfJxcktFI6VMqkO6YDzDE8XoOTE,76581
|
| 1026 |
+
babel/locale-data/uz_Cyrl_UZ.dat,sha256=MWJtHPdj_pF2h6abRP4wUwDWAUF4-zr7jBn2RQcZ0z8,635
|
| 1027 |
+
babel/locale-data/uz_Latn.dat,sha256=L5H7Xfz2Ho-vMqviRPC4ai0MnqoF9CIebiq7muISvSA,1292
|
| 1028 |
+
babel/locale-data/uz_Latn_UZ.dat,sha256=MWJtHPdj_pF2h6abRP4wUwDWAUF4-zr7jBn2RQcZ0z8,635
|
| 1029 |
+
babel/locale-data/vai.dat,sha256=T_MWlDAfbp9qgeArFd8yPDPbyThU15kFu19QTQqAlCE,17416
|
| 1030 |
+
babel/locale-data/vai_Latn.dat,sha256=MecJYJumVm7wCyCo-YeAY4eAon5WZ4ZqR0shQ3Pdpu8,14255
|
| 1031 |
+
babel/locale-data/vai_Latn_LR.dat,sha256=LdVmBAL7nzDp-Ab_uHidBAi2crIf9nXhf8tBNfa7xdI,617
|
| 1032 |
+
babel/locale-data/vai_Vaii.dat,sha256=l_IXC76zzJ2lPLfWfjWzSw6xVtFwr-x8LofcHQsSG_0,693
|
| 1033 |
+
babel/locale-data/vai_Vaii_LR.dat,sha256=LdVmBAL7nzDp-Ab_uHidBAi2crIf9nXhf8tBNfa7xdI,617
|
| 1034 |
+
babel/locale-data/ve.dat,sha256=5bInQioXkePSDbBerQqf4sYPTiB9-zpKuDokCXX5eNA,2372
|
| 1035 |
+
babel/locale-data/ve_ZA.dat,sha256=uJndHi9RMKtDWd58f_Q3g5WgXjL3W7KLQj91rVueabQ,635
|
| 1036 |
+
babel/locale-data/vec.dat,sha256=zokLfsgTK7cSP4KaSV8EMpPlHiOkI6tG3rWM7o7vcAM,160413
|
| 1037 |
+
babel/locale-data/vec_IT.dat,sha256=mC9jRfk9ndmkpRIpWZNCwdMwvxvB6QX6_9HanawdaUw,654
|
| 1038 |
+
babel/locale-data/vi.dat,sha256=F95a-fvLPIeJqOlwx4gr9TnWZ0VpSPyzNwJ0RPc1qE8,134138
|
| 1039 |
+
babel/locale-data/vi_VN.dat,sha256=cGwN0vw-qIaeA2g89U97N1xHSMmmaIVNPCLL2P_QJMk,635
|
| 1040 |
+
babel/locale-data/vmw.dat,sha256=mhERiGM-732X9KO0CThGEyjFtSbquT1_rmzYPnru2SM,1796
|
| 1041 |
+
babel/locale-data/vmw_MZ.dat,sha256=sz0j5RufN9oAzTalcjWNhKtCoEXzeRr5Cv6qCouK45E,636
|
| 1042 |
+
babel/locale-data/vo.dat,sha256=werwY25uwomUcf9q1dyQ8Rwgg2aCoLp78XUzBeSw0LY,4609
|
| 1043 |
+
babel/locale-data/vo_001.dat,sha256=iF2xY9XIdxC0mOYEp9hjYZp2EG-si_YaNYXri_60-4w,850
|
| 1044 |
+
babel/locale-data/vun.dat,sha256=VGNPlnoRipnocGYPgeb39d9MmE6fe5nTMWtCk4m1AEY,15373
|
| 1045 |
+
babel/locale-data/vun_TZ.dat,sha256=YKrOeOS1VnU3BWQ7HWtxjS-gMKJcKAPQLf4HTgkzf70,617
|
| 1046 |
+
babel/locale-data/wa.dat,sha256=1r6krApI8oecIKQt_9RzbpwSN0LcWSjlG34Y9Rfh07Y,880
|
| 1047 |
+
babel/locale-data/wa_BE.dat,sha256=j4YADQloo07Oek1j3aOrLYkzcFkrViS1UdRrA0Z56-o,653
|
| 1048 |
+
babel/locale-data/wae.dat,sha256=qBKStFqpkAruVDgeZJvX6U0X-hq_NkETTqgR2e7A4UQ,29641
|
| 1049 |
+
babel/locale-data/wae_CH.dat,sha256=Z0Wzu5Q9IVTnLGwWu54ozVx-fgnFz0IE3yrky8Y1IkQ,654
|
| 1050 |
+
babel/locale-data/wal.dat,sha256=AD9ZfdNNjEhX2n9T0ykd_XwEbXK-wxmsLqq39O4BjWU,8406
|
| 1051 |
+
babel/locale-data/wal_ET.dat,sha256=tNjeuU4GPTWtDmsroGmi4VUql0dA57v1tEtDF4rslVg,636
|
| 1052 |
+
babel/locale-data/wbp.dat,sha256=kzXK04f538n-PrJl6nRKIaYHMid6rJ4ACmzPcCz7NgU,746
|
| 1053 |
+
babel/locale-data/wbp_AU.dat,sha256=BT2E1-WiomuRrteCzN1_AfLyDUdEOm0ehT5miAiepBQ,636
|
| 1054 |
+
babel/locale-data/wo.dat,sha256=iB86SoTMrnphiHy_om1Yxs-J8L5YFWYlbmiQjK6jc2k,61849
|
| 1055 |
+
babel/locale-data/wo_SN.dat,sha256=fvlwe-ImWs04fsxSjTsXf8IPxEIiEi45BX8xhoBC_yg,616
|
| 1056 |
+
babel/locale-data/xh.dat,sha256=xRy095MO_brgAUoDB3UKwhgDvOkBlhJ3cWj9dM2fvHI,64334
|
| 1057 |
+
babel/locale-data/xh_ZA.dat,sha256=9p6wHW1sxOghJMAgsP6BC3RdUhuvLpHoCkqvjsCmPps,635
|
| 1058 |
+
babel/locale-data/xnr.dat,sha256=Ot10zi4F4H5Yqx6kIJGPay65Rm-Gam2eJ7kAOgoJoJ0,142585
|
| 1059 |
+
babel/locale-data/xnr_IN.dat,sha256=UbNwudCNihEFVZu3ymanDhJ52YoupG0SDGwmDByPhzQ,659
|
| 1060 |
+
babel/locale-data/xog.dat,sha256=V4U36ibPCWDoUMf31-o9mDCwylsYU0nZEx5pt-MWecM,15866
|
| 1061 |
+
babel/locale-data/xog_UG.dat,sha256=bMX0Tk5zS4P2LqlOLLpVP4nZxBFhS_qc-ndXjilDCNI,640
|
| 1062 |
+
babel/locale-data/yav.dat,sha256=UupgFFmPVcV-IgY3Fd8Y9GoOcOWgY1P22ZHuA-4QSMU,14543
|
| 1063 |
+
babel/locale-data/yav_CM.dat,sha256=CsaKwep5CARetyBX-JXHFvUVsFe1KTN4Pyz1Wh7NTHw,636
|
| 1064 |
+
babel/locale-data/yi.dat,sha256=OWr2zb3k_toEmkSXcPweqE13Tr5RhvlMm4z358uCQiY,24264
|
| 1065 |
+
babel/locale-data/yi_UA.dat,sha256=DesjWHTuxEBrjOeq8c-B82j4Hnwu0ElR2IH3fZPmq-A,635
|
| 1066 |
+
babel/locale-data/yo.dat,sha256=iWLg-08Fk9QJLZPuokgbCeXkyfyQNaov51TT3i1pKgY,110427
|
| 1067 |
+
babel/locale-data/yo_BJ.dat,sha256=CuxWXwNyq_dWEw-rEwu3-4HAmZfZGwPkljOt0ttEWRc,50090
|
| 1068 |
+
babel/locale-data/yo_NG.dat,sha256=BEIndIiMT1Mo18S5DAWpjefthptCVQkIPeVs0umSop0,616
|
| 1069 |
+
babel/locale-data/yrl.dat,sha256=2nwDuw5Q_dL4H2Oxl5ClzZU2Uw10j-koP5RgfnJ67y0,186854
|
| 1070 |
+
babel/locale-data/yrl_BR.dat,sha256=aUgLCNwgEORk2wtuez8AqkYahB8_mX41IWSqogt39YE,636
|
| 1071 |
+
babel/locale-data/yrl_CO.dat,sha256=pT0rllDKHZAUIK_itrkWP7irmih4im131Ume_wKzyks,9211
|
| 1072 |
+
babel/locale-data/yrl_VE.dat,sha256=_Tqu_pGUkzrd4M9SKXpn4g93z7Q5xlUMAtGvROS5x6M,9211
|
| 1073 |
+
babel/locale-data/yue.dat,sha256=lvTaoHXSVZHqcb5UCR8IeDiVRCE9IRsrDkhv0bGwzCg,143872
|
| 1074 |
+
babel/locale-data/yue_Hans.dat,sha256=ybTM8LU-H-QunhqnLmCQ9bE6zdsYMJPHdlh_hBv3AWk,145194
|
| 1075 |
+
babel/locale-data/yue_Hans_CN.dat,sha256=MOZnu5r0xokf672rwAXfgzG3VEeTfNlDbu36fR1bB6I,636
|
| 1076 |
+
babel/locale-data/yue_Hant.dat,sha256=76wefuhsGIjk0jT05KSTEU_pbb7AfNE2u56jdRoJaDM,1306
|
| 1077 |
+
babel/locale-data/yue_Hant_CN.dat,sha256=l0nSr9oItZCMdphhuVjzHML7FpqAKZorutkLijFAwm4,1196
|
| 1078 |
+
babel/locale-data/yue_Hant_HK.dat,sha256=eMZ7mOTEyKzQz0MDIjvP_Z57CS9nFIP4-Uf0Jpx1CY4,636
|
| 1079 |
+
babel/locale-data/yue_Hant_MO.dat,sha256=d6oknkpchm3cIK_Ylk-PjHAaPKhtyg8cGFVBdqtIJBg,636
|
| 1080 |
+
babel/locale-data/za.dat,sha256=5EbAmE-qqvt_e4geaFxBGJi81CVoZFK4dCcJ346P4yU,12705
|
| 1081 |
+
babel/locale-data/za_CN.dat,sha256=WzhnaughSM1C1twuKYBVrelLEer-guzT43a9yBNXCsg,635
|
| 1082 |
+
babel/locale-data/zgh.dat,sha256=Q2D9KQFgDfWk4fXOdEbPcLq3yX_zxjhlK_PVI61Ok4U,22018
|
| 1083 |
+
babel/locale-data/zgh_MA.dat,sha256=sV8aPBmHY23lKIzsRna-tPz3UiXoKCMQ1Ur2tCyx2YA,617
|
| 1084 |
+
babel/locale-data/zh.dat,sha256=SpSkmdVN5PX7CCdso1B-SyQZKMDTyZfZeT2l_kj2FoI,152100
|
| 1085 |
+
babel/locale-data/zh_Hans.dat,sha256=-wR64b65stjA2KWj4GWcBWiF3yI0A24p4K7wApj8qtc,1305
|
| 1086 |
+
babel/locale-data/zh_Hans_CN.dat,sha256=zz2qPpWEP9ba12T9cGsPXGI7Bg5LcmZ3NkAMiVTf61A,635
|
| 1087 |
+
babel/locale-data/zh_Hans_HK.dat,sha256=yPyZyU-xXSNyU1FYJIYpWwnh0d3uXOra9V9aj2j_YQU,3621
|
| 1088 |
+
babel/locale-data/zh_Hans_MO.dat,sha256=08kUXwHOXA0pRA8qIX7e4p0Nzl1XHSBjwhMh7f-nZBE,3752
|
| 1089 |
+
babel/locale-data/zh_Hans_MY.dat,sha256=iEFxl2XEm1zBzd1K0wXpiZFvU7l0UrNURh2p9DZdRLU,1300
|
| 1090 |
+
babel/locale-data/zh_Hans_SG.dat,sha256=OHZNiUfnteSXuzel-lZAMVgv58iiVTNhjq81T9Qu94s,3948
|
| 1091 |
+
babel/locale-data/zh_Hant.dat,sha256=31aRGt18bl6MdiI9iAozwltdkSQQ370TvzI8gid8CBI,154802
|
| 1092 |
+
babel/locale-data/zh_Hant_HK.dat,sha256=NXPCE_4pYgLatoeKLdQ0d8PQ-Mk_GeMF1s1JYX9m27M,49152
|
| 1093 |
+
babel/locale-data/zh_Hant_MO.dat,sha256=qCWPPEr87U1aemaIuf6nCYQ-Q3w_1HcXrYoncYVBd3g,657
|
| 1094 |
+
babel/locale-data/zh_Hant_MY.dat,sha256=3n4syQpQ9sXVe82sOEH7yQIdrU3dAtMhp7fEhzGN8_E,1203
|
| 1095 |
+
babel/locale-data/zh_Hant_TW.dat,sha256=5N4K8I3XG89knCaSoy97HGzTVOTiUcd_VmfvNJlA4Bg,635
|
| 1096 |
+
babel/locale-data/zh_Latn.dat,sha256=-wR64b65stjA2KWj4GWcBWiF3yI0A24p4K7wApj8qtc,1305
|
| 1097 |
+
babel/locale-data/zh_Latn_CN.dat,sha256=zz2qPpWEP9ba12T9cGsPXGI7Bg5LcmZ3NkAMiVTf61A,635
|
| 1098 |
+
babel/locale-data/zu.dat,sha256=e48g3oI1FjkROV3yHZ2GAwn_8wr2y3dMkj98NHW4X8Q,138626
|
| 1099 |
+
babel/locale-data/zu_ZA.dat,sha256=jHloBfkNbQETXgE-3xVxvESitWb994_-SoY0G4_JL5E,635
|
| 1100 |
+
babel/localedata.py,sha256=94b-NvjmQuidIpptiz2NM-d_3615AxMnV8rQcaWalp0,9133
|
| 1101 |
+
babel/localtime/__init__.py,sha256=EuxZJNvscBH6gM6XKF3pBLWaeRTK3GdNB12WxG3jhaA,1019
|
| 1102 |
+
babel/localtime/_fallback.py,sha256=9h1CFwVX3laiA2oaZgAywRqEr0ghI4PuTCBKkFgbamI,1199
|
| 1103 |
+
babel/localtime/_helpers.py,sha256=ZmLc8m46W-3GtsstLBdrw6BU3ZhSob8vKHkxgcZG9uw,1704
|
| 1104 |
+
babel/localtime/_unix.py,sha256=22Xkddk98UiDP1LkDDjvxTL9J_5UXIFyDbxj_gD-gv8,3903
|
| 1105 |
+
babel/localtime/_win32.py,sha256=cjImlpejBFxzeP-BqTN2OOevboB06kZAlT_GMqQPqAc,3198
|
| 1106 |
+
babel/messages/__init__.py,sha256=Km-kd7AFHT231GjF16TlHdlWn7s3zQh1xA9SbKrxkWQ,329
|
| 1107 |
+
babel/messages/_compat.py,sha256=DNyCNMwH5vXgl_pq7cUYz3VcRC2gIPqeQLO5nN5neWE,1163
|
| 1108 |
+
babel/messages/catalog.py,sha256=7mtA4SWOcJAK_wJvONRKt1AgOKmTVq7PTI1tP73-Jk8,38647
|
| 1109 |
+
babel/messages/checkers.py,sha256=KX50Rceb6rYuCndDYeDijvRe2w1jg4l7RQd7NpaXRY0,6209
|
| 1110 |
+
babel/messages/extract.py,sha256=Ss2wc-uYicxaZ1szXE2SPpWRYx4BxD6wsR-L0VFPd-M,36875
|
| 1111 |
+
babel/messages/frontend.py,sha256=hwbxnZkfeFRriKKAC8NHbb6rHSQ4xOVcE9pbP0Qce3M,47518
|
| 1112 |
+
babel/messages/jslexer.py,sha256=_RRI0T-MDby3sBykA4fEM28qDSBwqdjfsFR2HW6GlsA,7262
|
| 1113 |
+
babel/messages/mofile.py,sha256=GgCmyPLbbChLVMsC6Wk3fiEunnru4u8N0gEvoUxYDr0,6907
|
| 1114 |
+
babel/messages/plurals.py,sha256=Azqltuu3uRrDh0TM-nckgaHlsYLC9-_qcDmWvcRCOwI,7489
|
| 1115 |
+
babel/messages/pofile.py,sha256=aNynbXhhulJizuJQUYKvjbV7ktwWqHLINCzK3MdxZYE,25437
|
| 1116 |
+
babel/messages/setuptools_frontend.py,sha256=m1l9NHuawj1pSncZeC82cUJfdwxib_C7JSUb_2EhbUM,3485
|
| 1117 |
+
babel/numbers.py,sha256=meEj4-Rp5B_WXd-lmHGunWwrw8PL_1oyc5IOPePnHiI,63469
|
| 1118 |
+
babel/plural.py,sha256=zU3sxaLb-jYTcimy-QOZSnDuLv0it-BxcT5H9E49mM0,23186
|
| 1119 |
+
babel/py.typed,sha256=DtCsIDq6KOv2NOEdQjTbeMWJKRh6ZEL2E-6Mf1RLeMA,59
|
| 1120 |
+
babel/support.py,sha256=oYq9nmEbvqpSwTLO69hOZ1TGb51okrEoyFN6M8NklfM,27906
|
| 1121 |
+
babel/units.py,sha256=0WsfuBXU150pPwbznrnt6Mc6vyrij2d9yTJj9MXnbGw,13982
|
| 1122 |
+
babel/util.py,sha256=-Zch-KLaAZgpC4jGGV8twKH8R8pCwd731ozEkUUI1qg,9395
|
.venv/lib/python3.12/site-packages/babel-2.18.0.dist-info/REQUESTED
ADDED
|
File without changes
|
.venv/lib/python3.12/site-packages/babel-2.18.0.dist-info/WHEEL
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Wheel-Version: 1.0
|
| 2 |
+
Generator: setuptools (80.10.2)
|
| 3 |
+
Root-Is-Purelib: true
|
| 4 |
+
Tag: py3-none-any
|
| 5 |
+
|
.venv/lib/python3.12/site-packages/babel-2.18.0.dist-info/entry_points.txt
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[babel.checkers]
|
| 2 |
+
num_plurals = babel.messages.checkers:num_plurals
|
| 3 |
+
python_format = babel.messages.checkers:python_format
|
| 4 |
+
|
| 5 |
+
[babel.extractors]
|
| 6 |
+
ignore = babel.messages.extract:extract_nothing
|
| 7 |
+
javascript = babel.messages.extract:extract_javascript
|
| 8 |
+
python = babel.messages.extract:extract_python
|
| 9 |
+
|
| 10 |
+
[console_scripts]
|
| 11 |
+
pybabel = babel.messages.frontend:main
|
| 12 |
+
|
| 13 |
+
[distutils.commands]
|
| 14 |
+
compile_catalog = babel.messages.setuptools_frontend:compile_catalog
|
| 15 |
+
extract_messages = babel.messages.setuptools_frontend:extract_messages
|
| 16 |
+
init_catalog = babel.messages.setuptools_frontend:init_catalog
|
| 17 |
+
update_catalog = babel.messages.setuptools_frontend:update_catalog
|
| 18 |
+
|
| 19 |
+
[distutils.setup_keywords]
|
| 20 |
+
message_extractors = babel.messages.setuptools_frontend:check_message_extractors
|
.venv/lib/python3.12/site-packages/babel-2.18.0.dist-info/top_level.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
babel
|
.venv/lib/python3.12/site-packages/bluecodec-0.1.0.dist-info/INSTALLER
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
uv
|
.venv/lib/python3.12/site-packages/bluecodec-0.1.0.dist-info/METADATA
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Metadata-Version: 2.3
|
| 2 |
+
Name: bluecodec
|
| 3 |
+
Version: 0.1.0
|
| 4 |
+
Summary: Speech autoencoder codec
|
| 5 |
+
Requires-Dist: numpy
|
| 6 |
+
Requires-Dist: soundfile
|
| 7 |
+
Requires-Dist: tqdm
|
| 8 |
+
Requires-Dist: tensorboard
|
| 9 |
+
Requires-Dist: huggingface-hub
|
| 10 |
+
Requires-Dist: safetensors
|
| 11 |
+
Requires-Dist: torchcodec>=0.11.0
|
| 12 |
+
Requires-Dist: torch>=2.10.0 ; extra == 'cu128'
|
| 13 |
+
Requires-Dist: torchaudio>=2.10.0 ; extra == 'cu128'
|
| 14 |
+
Requires-Dist: torch>=2.10.0 ; extra == 'cu130'
|
| 15 |
+
Requires-Dist: torchaudio>=2.10.0 ; extra == 'cu130'
|
| 16 |
+
Requires-Python: >=3.12
|
| 17 |
+
Provides-Extra: cu128
|
| 18 |
+
Provides-Extra: cu130
|
| 19 |
+
Description-Content-Type: text/markdown
|
| 20 |
+
|
| 21 |
+
# BlueCodec
|
| 22 |
+
|
| 23 |
+
Speech autoencoder that compresses 44.1 kHz audio into a compact 24-dimensional continuous latent representation at ~86 Hz, then reconstructs the waveform.
|
| 24 |
+
|
| 25 |
+
## Installation
|
| 26 |
+
|
| 27 |
+
```bash
|
| 28 |
+
uv add "bluecodec @ git+https://github.com/maxmelichov/blue-codec.git"
|
| 29 |
+
```
|
| 30 |
+
|
| 31 |
+
## Usage
|
| 32 |
+
|
| 33 |
+
See `examples/` folder for a full working example.
|
| 34 |
+
|
| 35 |
+
## Pretrained Model
|
| 36 |
+
|
| 37 |
+
The model was trained on 2x NVIDIA RTX 3090 GPUs for 4 weeks for 1.5 million steps on 6 million files with different languages, totaling about 11,000 hours of audio.
|
| 38 |
+
|
| 39 |
+
Pretrained weights: [notmax123/blue-codec](https://huggingface.co/notmax123/blue-codec) on Hugging Face.
|
| 40 |
+
|
| 41 |
+
## Training
|
| 42 |
+
|
| 43 |
+
For detailed instructions on how to train the Autoencoder, please refer to the [Training Documentation](docs/training.md).
|
| 44 |
+
|
| 45 |
+
## License
|
| 46 |
+
|
| 47 |
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
.venv/lib/python3.12/site-packages/bluecodec-0.1.0.dist-info/RECORD
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
bluecodec-0.1.0.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2
|
| 2 |
+
bluecodec-0.1.0.dist-info/METADATA,sha256=ofBKAv7mhgZjOmm8TP2gNVx4Thq3A5o53HqrC6sRS9w,1453
|
| 3 |
+
bluecodec-0.1.0.dist-info/RECORD,,
|
| 4 |
+
bluecodec-0.1.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 5 |
+
bluecodec-0.1.0.dist-info/WHEEL,sha256=iHtWm8nRfs0VRdCYVXocAWFW8ppjHL-uTJkAdZJKOBM,80
|
| 6 |
+
bluecodec-0.1.0.dist-info/direct_url.json,sha256=l-Jtux_DZ1XgOcH0pyqqiMH_nNQk6yaUMbkLBH37r90,135
|
| 7 |
+
bluecodec-0.1.0.dist-info/uv_build.json,sha256=RBNvo1WzZ4oRRq0W9-hknpT7T8If536DEMBg9hyq_4o,2
|
| 8 |
+
bluecodec/__init__.py,sha256=k3UqXj6k0BYB1PaRIbvpn_9VnFSYW21bWODSHZgeGYI,1231
|
| 9 |
+
bluecodec/audio_utils.py,sha256=PnJwr0XwhTMdiRuvPGaSmrXAYhj_KjYK7JWqsPeP9Tk,929
|
| 10 |
+
bluecodec/autoencoder/README.md,sha256=kkzBLDSSsCUIoPSJRWGNt30EtZGpoZwgpao1wtl7e6M,5236
|
| 11 |
+
bluecodec/autoencoder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 12 |
+
bluecodec/autoencoder/discriminators.py,sha256=ZeSbv1xiwrcN8nU9U25pG6sNPVjA--iRBHuWB6cNIpY,5630
|
| 13 |
+
bluecodec/autoencoder/latent_decoder.py,sha256=MREvdU0YTpnro6rgQNJZbL6ARe-HdIkRNXVDrkPGHIA,6288
|
| 14 |
+
bluecodec/autoencoder/latent_encoder.py,sha256=O73AG2z1q7n2gDup9W5ef9IVTNOEf_96hqufW0wDFq8,1461
|
| 15 |
+
bluecodec/autoencoder/modules.py,sha256=uZrwZj1dhsYgcszUP96PBJw8W_FqRnON5VwQ3lUttd8,3126
|
| 16 |
+
bluecodec/autoencoder/vocoder.py,sha256=wHPsdnvkvhZtJWKzW-G3sRDqIvfN3tU5Ur-BETnWqqw,6140
|
| 17 |
+
bluecodec/utils.py,sha256=n96ULv5NFdpUSidROVujFbt3Nr6we5BcPMvAmgoq-Cs,3764
|
.venv/lib/python3.12/site-packages/bluecodec-0.1.0.dist-info/REQUESTED
ADDED
|
File without changes
|
.venv/lib/python3.12/site-packages/bluecodec-0.1.0.dist-info/WHEEL
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Wheel-Version: 1.0
|
| 2 |
+
Generator: uv 0.9.30
|
| 3 |
+
Root-Is-Purelib: true
|
| 4 |
+
Tag: py3-none-any
|
.venv/lib/python3.12/site-packages/bluecodec-0.1.0.dist-info/direct_url.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"url":"https://github.com/maxmelichov/blue-codec.git","vcs_info":{"vcs":"git","commit_id":"5bccc0abb28ef7782473b7ccabd80970e2728149"}}
|
.venv/lib/python3.12/site-packages/bluecodec-0.1.0.dist-info/uv_build.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{}
|
.venv/lib/python3.12/site-packages/certifi-2026.2.25.dist-info/INSTALLER
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
uv
|
.venv/lib/python3.12/site-packages/certifi-2026.2.25.dist-info/METADATA
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Metadata-Version: 2.4
|
| 2 |
+
Name: certifi
|
| 3 |
+
Version: 2026.2.25
|
| 4 |
+
Summary: Python package for providing Mozilla's CA Bundle.
|
| 5 |
+
Home-page: https://github.com/certifi/python-certifi
|
| 6 |
+
Author: Kenneth Reitz
|
| 7 |
+
Author-email: me@kennethreitz.com
|
| 8 |
+
License: MPL-2.0
|
| 9 |
+
Project-URL: Source, https://github.com/certifi/python-certifi
|
| 10 |
+
Classifier: Development Status :: 5 - Production/Stable
|
| 11 |
+
Classifier: Intended Audience :: Developers
|
| 12 |
+
Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
|
| 13 |
+
Classifier: Natural Language :: English
|
| 14 |
+
Classifier: Programming Language :: Python
|
| 15 |
+
Classifier: Programming Language :: Python :: 3
|
| 16 |
+
Classifier: Programming Language :: Python :: 3 :: Only
|
| 17 |
+
Classifier: Programming Language :: Python :: 3.7
|
| 18 |
+
Classifier: Programming Language :: Python :: 3.8
|
| 19 |
+
Classifier: Programming Language :: Python :: 3.9
|
| 20 |
+
Classifier: Programming Language :: Python :: 3.10
|
| 21 |
+
Classifier: Programming Language :: Python :: 3.11
|
| 22 |
+
Classifier: Programming Language :: Python :: 3.12
|
| 23 |
+
Classifier: Programming Language :: Python :: 3.13
|
| 24 |
+
Classifier: Programming Language :: Python :: 3.14
|
| 25 |
+
Requires-Python: >=3.7
|
| 26 |
+
License-File: LICENSE
|
| 27 |
+
Dynamic: author
|
| 28 |
+
Dynamic: author-email
|
| 29 |
+
Dynamic: classifier
|
| 30 |
+
Dynamic: description
|
| 31 |
+
Dynamic: home-page
|
| 32 |
+
Dynamic: license
|
| 33 |
+
Dynamic: license-file
|
| 34 |
+
Dynamic: project-url
|
| 35 |
+
Dynamic: requires-python
|
| 36 |
+
Dynamic: summary
|
| 37 |
+
|
| 38 |
+
Certifi: Python SSL Certificates
|
| 39 |
+
================================
|
| 40 |
+
|
| 41 |
+
Certifi provides Mozilla's carefully curated collection of Root Certificates for
|
| 42 |
+
validating the trustworthiness of SSL certificates while verifying the identity
|
| 43 |
+
of TLS hosts. It has been extracted from the `Requests`_ project.
|
| 44 |
+
|
| 45 |
+
Installation
|
| 46 |
+
------------
|
| 47 |
+
|
| 48 |
+
``certifi`` is available on PyPI. Simply install it with ``pip``::
|
| 49 |
+
|
| 50 |
+
$ pip install certifi
|
| 51 |
+
|
| 52 |
+
Usage
|
| 53 |
+
-----
|
| 54 |
+
|
| 55 |
+
To reference the installed certificate authority (CA) bundle, you can use the
|
| 56 |
+
built-in function::
|
| 57 |
+
|
| 58 |
+
>>> import certifi
|
| 59 |
+
|
| 60 |
+
>>> certifi.where()
|
| 61 |
+
'/usr/local/lib/python3.7/site-packages/certifi/cacert.pem'
|
| 62 |
+
|
| 63 |
+
Or from the command line::
|
| 64 |
+
|
| 65 |
+
$ python -m certifi
|
| 66 |
+
/usr/local/lib/python3.7/site-packages/certifi/cacert.pem
|
| 67 |
+
|
| 68 |
+
Enjoy!
|
| 69 |
+
|
| 70 |
+
.. _`Requests`: https://requests.readthedocs.io/en/master/
|
| 71 |
+
|
| 72 |
+
Addition/Removal of Certificates
|
| 73 |
+
--------------------------------
|
| 74 |
+
|
| 75 |
+
Certifi does not support any addition/removal or other modification of the
|
| 76 |
+
CA trust store content. This project is intended to provide a reliable and
|
| 77 |
+
highly portable root of trust to python deployments. Look to upstream projects
|
| 78 |
+
for methods to use alternate trust.
|
.venv/lib/python3.12/site-packages/certifi-2026.2.25.dist-info/RECORD
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
certifi-2026.2.25.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2
|
| 2 |
+
certifi-2026.2.25.dist-info/METADATA,sha256=4NMuGXdg_hBiRA3paKVXYcDmE3VXEBWxTvCL2xlDyPU,2474
|
| 3 |
+
certifi-2026.2.25.dist-info/RECORD,,
|
| 4 |
+
certifi-2026.2.25.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 5 |
+
certifi-2026.2.25.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
|
| 6 |
+
certifi-2026.2.25.dist-info/licenses/LICENSE,sha256=6TcW2mucDVpKHfYP5pWzcPBpVgPSH2-D8FPkLPwQyvc,989
|
| 7 |
+
certifi-2026.2.25.dist-info/top_level.txt,sha256=KMu4vUCfsjLrkPbSNdgdekS-pVJzBAJFO__nI8NF6-U,8
|
| 8 |
+
certifi/__init__.py,sha256=c9eaYufv1pSLl0Q8QNcMiMLLH4WquDcxdPyKjmI4opY,94
|
| 9 |
+
certifi/__main__.py,sha256=xBBoj905TUWBLRGANOcf7oi6e-3dMP4cEoG9OyMs11g,243
|
| 10 |
+
certifi/cacert.pem,sha256=_JFloSQDJj5-v72te-ej6sD6XTJdPHBGXyjTaQByyig,272441
|
| 11 |
+
certifi/core.py,sha256=XFXycndG5pf37ayeF8N32HUuDafsyhkVMbO4BAPWHa0,3394
|
| 12 |
+
certifi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
.venv/lib/python3.12/site-packages/certifi-2026.2.25.dist-info/REQUESTED
ADDED
|
File without changes
|
.venv/lib/python3.12/site-packages/certifi-2026.2.25.dist-info/WHEEL
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Wheel-Version: 1.0
|
| 2 |
+
Generator: setuptools (82.0.0)
|
| 3 |
+
Root-Is-Purelib: true
|
| 4 |
+
Tag: py3-none-any
|
| 5 |
+
|
.venv/lib/python3.12/site-packages/certifi-2026.2.25.dist-info/top_level.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
certifi
|
.venv/lib/python3.12/site-packages/cffi/__init__.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__all__ = ['FFI', 'VerificationError', 'VerificationMissing', 'CDefError',
|
| 2 |
+
'FFIError']
|
| 3 |
+
|
| 4 |
+
from .api import FFI
|
| 5 |
+
from .error import CDefError, FFIError, VerificationError, VerificationMissing
|
| 6 |
+
from .error import PkgConfigError
|
| 7 |
+
|
| 8 |
+
__version__ = "2.0.0"
|
| 9 |
+
__version_info__ = (2, 0, 0)
|
| 10 |
+
|
| 11 |
+
# The verifier module file names are based on the CRC32 of a string that
|
| 12 |
+
# contains the following version number. It may be older than __version__
|
| 13 |
+
# if nothing is clearly incompatible.
|
| 14 |
+
__version_verifier_modules__ = "0.8.6"
|
.venv/lib/python3.12/site-packages/cffi/_cffi_errors.h
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#ifndef CFFI_MESSAGEBOX
|
| 2 |
+
# ifdef _MSC_VER
|
| 3 |
+
# define CFFI_MESSAGEBOX 1
|
| 4 |
+
# else
|
| 5 |
+
# define CFFI_MESSAGEBOX 0
|
| 6 |
+
# endif
|
| 7 |
+
#endif
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
#if CFFI_MESSAGEBOX
|
| 11 |
+
/* Windows only: logic to take the Python-CFFI embedding logic
|
| 12 |
+
initialization errors and display them in a background thread
|
| 13 |
+
with MessageBox. The idea is that if the whole program closes
|
| 14 |
+
as a result of this problem, then likely it is already a console
|
| 15 |
+
program and you can read the stderr output in the console too.
|
| 16 |
+
If it is not a console program, then it will likely show its own
|
| 17 |
+
dialog to complain, or generally not abruptly close, and for this
|
| 18 |
+
case the background thread should stay alive.
|
| 19 |
+
*/
|
| 20 |
+
static void *volatile _cffi_bootstrap_text;
|
| 21 |
+
|
| 22 |
+
static PyObject *_cffi_start_error_capture(void)
|
| 23 |
+
{
|
| 24 |
+
PyObject *result = NULL;
|
| 25 |
+
PyObject *x, *m, *bi;
|
| 26 |
+
|
| 27 |
+
if (InterlockedCompareExchangePointer(&_cffi_bootstrap_text,
|
| 28 |
+
(void *)1, NULL) != NULL)
|
| 29 |
+
return (PyObject *)1;
|
| 30 |
+
|
| 31 |
+
m = PyImport_AddModule("_cffi_error_capture");
|
| 32 |
+
if (m == NULL)
|
| 33 |
+
goto error;
|
| 34 |
+
|
| 35 |
+
result = PyModule_GetDict(m);
|
| 36 |
+
if (result == NULL)
|
| 37 |
+
goto error;
|
| 38 |
+
|
| 39 |
+
#if PY_MAJOR_VERSION >= 3
|
| 40 |
+
bi = PyImport_ImportModule("builtins");
|
| 41 |
+
#else
|
| 42 |
+
bi = PyImport_ImportModule("__builtin__");
|
| 43 |
+
#endif
|
| 44 |
+
if (bi == NULL)
|
| 45 |
+
goto error;
|
| 46 |
+
PyDict_SetItemString(result, "__builtins__", bi);
|
| 47 |
+
Py_DECREF(bi);
|
| 48 |
+
|
| 49 |
+
x = PyRun_String(
|
| 50 |
+
"import sys\n"
|
| 51 |
+
"class FileLike:\n"
|
| 52 |
+
" def write(self, x):\n"
|
| 53 |
+
" try:\n"
|
| 54 |
+
" of.write(x)\n"
|
| 55 |
+
" except: pass\n"
|
| 56 |
+
" self.buf += x\n"
|
| 57 |
+
" def flush(self):\n"
|
| 58 |
+
" pass\n"
|
| 59 |
+
"fl = FileLike()\n"
|
| 60 |
+
"fl.buf = ''\n"
|
| 61 |
+
"of = sys.stderr\n"
|
| 62 |
+
"sys.stderr = fl\n"
|
| 63 |
+
"def done():\n"
|
| 64 |
+
" sys.stderr = of\n"
|
| 65 |
+
" return fl.buf\n", /* make sure the returned value stays alive */
|
| 66 |
+
Py_file_input,
|
| 67 |
+
result, result);
|
| 68 |
+
Py_XDECREF(x);
|
| 69 |
+
|
| 70 |
+
error:
|
| 71 |
+
if (PyErr_Occurred())
|
| 72 |
+
{
|
| 73 |
+
PyErr_WriteUnraisable(Py_None);
|
| 74 |
+
PyErr_Clear();
|
| 75 |
+
}
|
| 76 |
+
return result;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
#pragma comment(lib, "user32.lib")
|
| 80 |
+
|
| 81 |
+
static DWORD WINAPI _cffi_bootstrap_dialog(LPVOID ignored)
|
| 82 |
+
{
|
| 83 |
+
Sleep(666); /* may be interrupted if the whole process is closing */
|
| 84 |
+
#if PY_MAJOR_VERSION >= 3
|
| 85 |
+
MessageBoxW(NULL, (wchar_t *)_cffi_bootstrap_text,
|
| 86 |
+
L"Python-CFFI error",
|
| 87 |
+
MB_OK | MB_ICONERROR);
|
| 88 |
+
#else
|
| 89 |
+
MessageBoxA(NULL, (char *)_cffi_bootstrap_text,
|
| 90 |
+
"Python-CFFI error",
|
| 91 |
+
MB_OK | MB_ICONERROR);
|
| 92 |
+
#endif
|
| 93 |
+
_cffi_bootstrap_text = NULL;
|
| 94 |
+
return 0;
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
static void _cffi_stop_error_capture(PyObject *ecap)
|
| 98 |
+
{
|
| 99 |
+
PyObject *s;
|
| 100 |
+
void *text;
|
| 101 |
+
|
| 102 |
+
if (ecap == (PyObject *)1)
|
| 103 |
+
return;
|
| 104 |
+
|
| 105 |
+
if (ecap == NULL)
|
| 106 |
+
goto error;
|
| 107 |
+
|
| 108 |
+
s = PyRun_String("done()", Py_eval_input, ecap, ecap);
|
| 109 |
+
if (s == NULL)
|
| 110 |
+
goto error;
|
| 111 |
+
|
| 112 |
+
/* Show a dialog box, but in a background thread, and
|
| 113 |
+
never show multiple dialog boxes at once. */
|
| 114 |
+
#if PY_MAJOR_VERSION >= 3
|
| 115 |
+
text = PyUnicode_AsWideCharString(s, NULL);
|
| 116 |
+
#else
|
| 117 |
+
text = PyString_AsString(s);
|
| 118 |
+
#endif
|
| 119 |
+
|
| 120 |
+
_cffi_bootstrap_text = text;
|
| 121 |
+
|
| 122 |
+
if (text != NULL)
|
| 123 |
+
{
|
| 124 |
+
HANDLE h;
|
| 125 |
+
h = CreateThread(NULL, 0, _cffi_bootstrap_dialog,
|
| 126 |
+
NULL, 0, NULL);
|
| 127 |
+
if (h != NULL)
|
| 128 |
+
CloseHandle(h);
|
| 129 |
+
}
|
| 130 |
+
/* decref the string, but it should stay alive as 'fl.buf'
|
| 131 |
+
in the small module above. It will really be freed only if
|
| 132 |
+
we later get another similar error. So it's a leak of at
|
| 133 |
+
most one copy of the small module. That's fine for this
|
| 134 |
+
situation which is usually a "fatal error" anyway. */
|
| 135 |
+
Py_DECREF(s);
|
| 136 |
+
PyErr_Clear();
|
| 137 |
+
return;
|
| 138 |
+
|
| 139 |
+
error:
|
| 140 |
+
_cffi_bootstrap_text = NULL;
|
| 141 |
+
PyErr_Clear();
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
#else
|
| 145 |
+
|
| 146 |
+
static PyObject *_cffi_start_error_capture(void) { return NULL; }
|
| 147 |
+
static void _cffi_stop_error_capture(PyObject *ecap) { }
|
| 148 |
+
|
| 149 |
+
#endif
|
.venv/lib/python3.12/site-packages/cffi/_cffi_include.h
ADDED
|
@@ -0,0 +1,389 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#define _CFFI_
|
| 2 |
+
|
| 3 |
+
/* We try to define Py_LIMITED_API before including Python.h.
|
| 4 |
+
|
| 5 |
+
Mess: we can only define it if Py_DEBUG, Py_TRACE_REFS and
|
| 6 |
+
Py_REF_DEBUG are not defined. This is a best-effort approximation:
|
| 7 |
+
we can learn about Py_DEBUG from pyconfig.h, but it is unclear if
|
| 8 |
+
the same works for the other two macros. Py_DEBUG implies them,
|
| 9 |
+
but not the other way around.
|
| 10 |
+
|
| 11 |
+
The implementation is messy (issue #350): on Windows, with _MSC_VER,
|
| 12 |
+
we have to define Py_LIMITED_API even before including pyconfig.h.
|
| 13 |
+
In that case, we guess what pyconfig.h will do to the macros above,
|
| 14 |
+
and check our guess after the #include.
|
| 15 |
+
|
| 16 |
+
Note that on Windows, with CPython 3.x, you need >= 3.5 and virtualenv
|
| 17 |
+
version >= 16.0.0. With older versions of either, you don't get a
|
| 18 |
+
copy of PYTHON3.DLL in the virtualenv. We can't check the version of
|
| 19 |
+
CPython *before* we even include pyconfig.h. ffi.set_source() puts
|
| 20 |
+
a ``#define _CFFI_NO_LIMITED_API'' at the start of this file if it is
|
| 21 |
+
running on Windows < 3.5, as an attempt at fixing it, but that's
|
| 22 |
+
arguably wrong because it may not be the target version of Python.
|
| 23 |
+
Still better than nothing I guess. As another workaround, you can
|
| 24 |
+
remove the definition of Py_LIMITED_API here.
|
| 25 |
+
|
| 26 |
+
See also 'py_limited_api' in cffi/setuptools_ext.py.
|
| 27 |
+
*/
|
| 28 |
+
#if !defined(_CFFI_USE_EMBEDDING) && !defined(Py_LIMITED_API)
|
| 29 |
+
# ifdef _MSC_VER
|
| 30 |
+
# if !defined(_DEBUG) && !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) && !defined(_CFFI_NO_LIMITED_API)
|
| 31 |
+
# define Py_LIMITED_API
|
| 32 |
+
# endif
|
| 33 |
+
# include <pyconfig.h>
|
| 34 |
+
/* sanity-check: Py_LIMITED_API will cause crashes if any of these
|
| 35 |
+
are also defined. Normally, the Python file PC/pyconfig.h does not
|
| 36 |
+
cause any of these to be defined, with the exception that _DEBUG
|
| 37 |
+
causes Py_DEBUG. Double-check that. */
|
| 38 |
+
# ifdef Py_LIMITED_API
|
| 39 |
+
# if defined(Py_DEBUG)
|
| 40 |
+
# error "pyconfig.h unexpectedly defines Py_DEBUG, but Py_LIMITED_API is set"
|
| 41 |
+
# endif
|
| 42 |
+
# if defined(Py_TRACE_REFS)
|
| 43 |
+
# error "pyconfig.h unexpectedly defines Py_TRACE_REFS, but Py_LIMITED_API is set"
|
| 44 |
+
# endif
|
| 45 |
+
# if defined(Py_REF_DEBUG)
|
| 46 |
+
# error "pyconfig.h unexpectedly defines Py_REF_DEBUG, but Py_LIMITED_API is set"
|
| 47 |
+
# endif
|
| 48 |
+
# endif
|
| 49 |
+
# else
|
| 50 |
+
# include <pyconfig.h>
|
| 51 |
+
# if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) && !defined(_CFFI_NO_LIMITED_API)
|
| 52 |
+
# define Py_LIMITED_API
|
| 53 |
+
# endif
|
| 54 |
+
# endif
|
| 55 |
+
#endif
|
| 56 |
+
|
| 57 |
+
#include <Python.h>
|
| 58 |
+
#ifdef __cplusplus
|
| 59 |
+
extern "C" {
|
| 60 |
+
#endif
|
| 61 |
+
#include <stddef.h>
|
| 62 |
+
#include "parse_c_type.h"
|
| 63 |
+
|
| 64 |
+
/* this block of #ifs should be kept exactly identical between
|
| 65 |
+
c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py
|
| 66 |
+
and cffi/_cffi_include.h */
|
| 67 |
+
#if defined(_MSC_VER)
|
| 68 |
+
# include <malloc.h> /* for alloca() */
|
| 69 |
+
# if _MSC_VER < 1600 /* MSVC < 2010 */
|
| 70 |
+
typedef __int8 int8_t;
|
| 71 |
+
typedef __int16 int16_t;
|
| 72 |
+
typedef __int32 int32_t;
|
| 73 |
+
typedef __int64 int64_t;
|
| 74 |
+
typedef unsigned __int8 uint8_t;
|
| 75 |
+
typedef unsigned __int16 uint16_t;
|
| 76 |
+
typedef unsigned __int32 uint32_t;
|
| 77 |
+
typedef unsigned __int64 uint64_t;
|
| 78 |
+
typedef __int8 int_least8_t;
|
| 79 |
+
typedef __int16 int_least16_t;
|
| 80 |
+
typedef __int32 int_least32_t;
|
| 81 |
+
typedef __int64 int_least64_t;
|
| 82 |
+
typedef unsigned __int8 uint_least8_t;
|
| 83 |
+
typedef unsigned __int16 uint_least16_t;
|
| 84 |
+
typedef unsigned __int32 uint_least32_t;
|
| 85 |
+
typedef unsigned __int64 uint_least64_t;
|
| 86 |
+
typedef __int8 int_fast8_t;
|
| 87 |
+
typedef __int16 int_fast16_t;
|
| 88 |
+
typedef __int32 int_fast32_t;
|
| 89 |
+
typedef __int64 int_fast64_t;
|
| 90 |
+
typedef unsigned __int8 uint_fast8_t;
|
| 91 |
+
typedef unsigned __int16 uint_fast16_t;
|
| 92 |
+
typedef unsigned __int32 uint_fast32_t;
|
| 93 |
+
typedef unsigned __int64 uint_fast64_t;
|
| 94 |
+
typedef __int64 intmax_t;
|
| 95 |
+
typedef unsigned __int64 uintmax_t;
|
| 96 |
+
# else
|
| 97 |
+
# include <stdint.h>
|
| 98 |
+
# endif
|
| 99 |
+
# if _MSC_VER < 1800 /* MSVC < 2013 */
|
| 100 |
+
# ifndef __cplusplus
|
| 101 |
+
typedef unsigned char _Bool;
|
| 102 |
+
# endif
|
| 103 |
+
# endif
|
| 104 |
+
# define _cffi_float_complex_t _Fcomplex /* include <complex.h> for it */
|
| 105 |
+
# define _cffi_double_complex_t _Dcomplex /* include <complex.h> for it */
|
| 106 |
+
#else
|
| 107 |
+
# include <stdint.h>
|
| 108 |
+
# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux)
|
| 109 |
+
# include <alloca.h>
|
| 110 |
+
# endif
|
| 111 |
+
# define _cffi_float_complex_t float _Complex
|
| 112 |
+
# define _cffi_double_complex_t double _Complex
|
| 113 |
+
#endif
|
| 114 |
+
|
| 115 |
+
#ifdef __GNUC__
|
| 116 |
+
# define _CFFI_UNUSED_FN __attribute__((unused))
|
| 117 |
+
#else
|
| 118 |
+
# define _CFFI_UNUSED_FN /* nothing */
|
| 119 |
+
#endif
|
| 120 |
+
|
| 121 |
+
#ifdef __cplusplus
|
| 122 |
+
# ifndef _Bool
|
| 123 |
+
typedef bool _Bool; /* semi-hackish: C++ has no _Bool; bool is builtin */
|
| 124 |
+
# endif
|
| 125 |
+
#endif
|
| 126 |
+
|
| 127 |
+
/********** CPython-specific section **********/
|
| 128 |
+
#ifndef PYPY_VERSION
|
| 129 |
+
|
| 130 |
+
|
| 131 |
+
#if PY_MAJOR_VERSION >= 3
|
| 132 |
+
# define PyInt_FromLong PyLong_FromLong
|
| 133 |
+
#endif
|
| 134 |
+
|
| 135 |
+
#define _cffi_from_c_double PyFloat_FromDouble
|
| 136 |
+
#define _cffi_from_c_float PyFloat_FromDouble
|
| 137 |
+
#define _cffi_from_c_long PyInt_FromLong
|
| 138 |
+
#define _cffi_from_c_ulong PyLong_FromUnsignedLong
|
| 139 |
+
#define _cffi_from_c_longlong PyLong_FromLongLong
|
| 140 |
+
#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong
|
| 141 |
+
#define _cffi_from_c__Bool PyBool_FromLong
|
| 142 |
+
|
| 143 |
+
#define _cffi_to_c_double PyFloat_AsDouble
|
| 144 |
+
#define _cffi_to_c_float PyFloat_AsDouble
|
| 145 |
+
|
| 146 |
+
#define _cffi_from_c_int(x, type) \
|
| 147 |
+
(((type)-1) > 0 ? /* unsigned */ \
|
| 148 |
+
(sizeof(type) < sizeof(long) ? \
|
| 149 |
+
PyInt_FromLong((long)x) : \
|
| 150 |
+
sizeof(type) == sizeof(long) ? \
|
| 151 |
+
PyLong_FromUnsignedLong((unsigned long)x) : \
|
| 152 |
+
PyLong_FromUnsignedLongLong((unsigned long long)x)) : \
|
| 153 |
+
(sizeof(type) <= sizeof(long) ? \
|
| 154 |
+
PyInt_FromLong((long)x) : \
|
| 155 |
+
PyLong_FromLongLong((long long)x)))
|
| 156 |
+
|
| 157 |
+
#define _cffi_to_c_int(o, type) \
|
| 158 |
+
((type)( \
|
| 159 |
+
sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \
|
| 160 |
+
: (type)_cffi_to_c_i8(o)) : \
|
| 161 |
+
sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \
|
| 162 |
+
: (type)_cffi_to_c_i16(o)) : \
|
| 163 |
+
sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \
|
| 164 |
+
: (type)_cffi_to_c_i32(o)) : \
|
| 165 |
+
sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \
|
| 166 |
+
: (type)_cffi_to_c_i64(o)) : \
|
| 167 |
+
(Py_FatalError("unsupported size for type " #type), (type)0)))
|
| 168 |
+
|
| 169 |
+
#define _cffi_to_c_i8 \
|
| 170 |
+
((int(*)(PyObject *))_cffi_exports[1])
|
| 171 |
+
#define _cffi_to_c_u8 \
|
| 172 |
+
((int(*)(PyObject *))_cffi_exports[2])
|
| 173 |
+
#define _cffi_to_c_i16 \
|
| 174 |
+
((int(*)(PyObject *))_cffi_exports[3])
|
| 175 |
+
#define _cffi_to_c_u16 \
|
| 176 |
+
((int(*)(PyObject *))_cffi_exports[4])
|
| 177 |
+
#define _cffi_to_c_i32 \
|
| 178 |
+
((int(*)(PyObject *))_cffi_exports[5])
|
| 179 |
+
#define _cffi_to_c_u32 \
|
| 180 |
+
((unsigned int(*)(PyObject *))_cffi_exports[6])
|
| 181 |
+
#define _cffi_to_c_i64 \
|
| 182 |
+
((long long(*)(PyObject *))_cffi_exports[7])
|
| 183 |
+
#define _cffi_to_c_u64 \
|
| 184 |
+
((unsigned long long(*)(PyObject *))_cffi_exports[8])
|
| 185 |
+
#define _cffi_to_c_char \
|
| 186 |
+
((int(*)(PyObject *))_cffi_exports[9])
|
| 187 |
+
#define _cffi_from_c_pointer \
|
| 188 |
+
((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[10])
|
| 189 |
+
#define _cffi_to_c_pointer \
|
| 190 |
+
((char *(*)(PyObject *, struct _cffi_ctypedescr *))_cffi_exports[11])
|
| 191 |
+
#define _cffi_get_struct_layout \
|
| 192 |
+
not used any more
|
| 193 |
+
#define _cffi_restore_errno \
|
| 194 |
+
((void(*)(void))_cffi_exports[13])
|
| 195 |
+
#define _cffi_save_errno \
|
| 196 |
+
((void(*)(void))_cffi_exports[14])
|
| 197 |
+
#define _cffi_from_c_char \
|
| 198 |
+
((PyObject *(*)(char))_cffi_exports[15])
|
| 199 |
+
#define _cffi_from_c_deref \
|
| 200 |
+
((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[16])
|
| 201 |
+
#define _cffi_to_c \
|
| 202 |
+
((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[17])
|
| 203 |
+
#define _cffi_from_c_struct \
|
| 204 |
+
((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[18])
|
| 205 |
+
#define _cffi_to_c_wchar_t \
|
| 206 |
+
((_cffi_wchar_t(*)(PyObject *))_cffi_exports[19])
|
| 207 |
+
#define _cffi_from_c_wchar_t \
|
| 208 |
+
((PyObject *(*)(_cffi_wchar_t))_cffi_exports[20])
|
| 209 |
+
#define _cffi_to_c_long_double \
|
| 210 |
+
((long double(*)(PyObject *))_cffi_exports[21])
|
| 211 |
+
#define _cffi_to_c__Bool \
|
| 212 |
+
((_Bool(*)(PyObject *))_cffi_exports[22])
|
| 213 |
+
#define _cffi_prepare_pointer_call_argument \
|
| 214 |
+
((Py_ssize_t(*)(struct _cffi_ctypedescr *, \
|
| 215 |
+
PyObject *, char **))_cffi_exports[23])
|
| 216 |
+
#define _cffi_convert_array_from_object \
|
| 217 |
+
((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[24])
|
| 218 |
+
#define _CFFI_CPIDX 25
|
| 219 |
+
#define _cffi_call_python \
|
| 220 |
+
((void(*)(struct _cffi_externpy_s *, char *))_cffi_exports[_CFFI_CPIDX])
|
| 221 |
+
#define _cffi_to_c_wchar3216_t \
|
| 222 |
+
((int(*)(PyObject *))_cffi_exports[26])
|
| 223 |
+
#define _cffi_from_c_wchar3216_t \
|
| 224 |
+
((PyObject *(*)(int))_cffi_exports[27])
|
| 225 |
+
#define _CFFI_NUM_EXPORTS 28
|
| 226 |
+
|
| 227 |
+
struct _cffi_ctypedescr;
|
| 228 |
+
|
| 229 |
+
static void *_cffi_exports[_CFFI_NUM_EXPORTS];
|
| 230 |
+
|
| 231 |
+
#define _cffi_type(index) ( \
|
| 232 |
+
assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \
|
| 233 |
+
(struct _cffi_ctypedescr *)_cffi_types[index])
|
| 234 |
+
|
| 235 |
+
static PyObject *_cffi_init(const char *module_name, Py_ssize_t version,
|
| 236 |
+
const struct _cffi_type_context_s *ctx)
|
| 237 |
+
{
|
| 238 |
+
PyObject *module, *o_arg, *new_module;
|
| 239 |
+
void *raw[] = {
|
| 240 |
+
(void *)module_name,
|
| 241 |
+
(void *)version,
|
| 242 |
+
(void *)_cffi_exports,
|
| 243 |
+
(void *)ctx,
|
| 244 |
+
};
|
| 245 |
+
|
| 246 |
+
module = PyImport_ImportModule("_cffi_backend");
|
| 247 |
+
if (module == NULL)
|
| 248 |
+
goto failure;
|
| 249 |
+
|
| 250 |
+
o_arg = PyLong_FromVoidPtr((void *)raw);
|
| 251 |
+
if (o_arg == NULL)
|
| 252 |
+
goto failure;
|
| 253 |
+
|
| 254 |
+
new_module = PyObject_CallMethod(
|
| 255 |
+
module, (char *)"_init_cffi_1_0_external_module", (char *)"O", o_arg);
|
| 256 |
+
|
| 257 |
+
Py_DECREF(o_arg);
|
| 258 |
+
Py_DECREF(module);
|
| 259 |
+
return new_module;
|
| 260 |
+
|
| 261 |
+
failure:
|
| 262 |
+
Py_XDECREF(module);
|
| 263 |
+
return NULL;
|
| 264 |
+
}
|
| 265 |
+
|
| 266 |
+
|
| 267 |
+
#ifdef HAVE_WCHAR_H
|
| 268 |
+
typedef wchar_t _cffi_wchar_t;
|
| 269 |
+
#else
|
| 270 |
+
typedef uint16_t _cffi_wchar_t; /* same random pick as _cffi_backend.c */
|
| 271 |
+
#endif
|
| 272 |
+
|
| 273 |
+
_CFFI_UNUSED_FN static uint16_t _cffi_to_c_char16_t(PyObject *o)
|
| 274 |
+
{
|
| 275 |
+
if (sizeof(_cffi_wchar_t) == 2)
|
| 276 |
+
return (uint16_t)_cffi_to_c_wchar_t(o);
|
| 277 |
+
else
|
| 278 |
+
return (uint16_t)_cffi_to_c_wchar3216_t(o);
|
| 279 |
+
}
|
| 280 |
+
|
| 281 |
+
_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char16_t(uint16_t x)
|
| 282 |
+
{
|
| 283 |
+
if (sizeof(_cffi_wchar_t) == 2)
|
| 284 |
+
return _cffi_from_c_wchar_t((_cffi_wchar_t)x);
|
| 285 |
+
else
|
| 286 |
+
return _cffi_from_c_wchar3216_t((int)x);
|
| 287 |
+
}
|
| 288 |
+
|
| 289 |
+
_CFFI_UNUSED_FN static int _cffi_to_c_char32_t(PyObject *o)
|
| 290 |
+
{
|
| 291 |
+
if (sizeof(_cffi_wchar_t) == 4)
|
| 292 |
+
return (int)_cffi_to_c_wchar_t(o);
|
| 293 |
+
else
|
| 294 |
+
return (int)_cffi_to_c_wchar3216_t(o);
|
| 295 |
+
}
|
| 296 |
+
|
| 297 |
+
_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char32_t(unsigned int x)
|
| 298 |
+
{
|
| 299 |
+
if (sizeof(_cffi_wchar_t) == 4)
|
| 300 |
+
return _cffi_from_c_wchar_t((_cffi_wchar_t)x);
|
| 301 |
+
else
|
| 302 |
+
return _cffi_from_c_wchar3216_t((int)x);
|
| 303 |
+
}
|
| 304 |
+
|
| 305 |
+
union _cffi_union_alignment_u {
|
| 306 |
+
unsigned char m_char;
|
| 307 |
+
unsigned short m_short;
|
| 308 |
+
unsigned int m_int;
|
| 309 |
+
unsigned long m_long;
|
| 310 |
+
unsigned long long m_longlong;
|
| 311 |
+
float m_float;
|
| 312 |
+
double m_double;
|
| 313 |
+
long double m_longdouble;
|
| 314 |
+
};
|
| 315 |
+
|
| 316 |
+
struct _cffi_freeme_s {
|
| 317 |
+
struct _cffi_freeme_s *next;
|
| 318 |
+
union _cffi_union_alignment_u alignment;
|
| 319 |
+
};
|
| 320 |
+
|
| 321 |
+
_CFFI_UNUSED_FN static int
|
| 322 |
+
_cffi_convert_array_argument(struct _cffi_ctypedescr *ctptr, PyObject *arg,
|
| 323 |
+
char **output_data, Py_ssize_t datasize,
|
| 324 |
+
struct _cffi_freeme_s **freeme)
|
| 325 |
+
{
|
| 326 |
+
char *p;
|
| 327 |
+
if (datasize < 0)
|
| 328 |
+
return -1;
|
| 329 |
+
|
| 330 |
+
p = *output_data;
|
| 331 |
+
if (p == NULL) {
|
| 332 |
+
struct _cffi_freeme_s *fp = (struct _cffi_freeme_s *)PyObject_Malloc(
|
| 333 |
+
offsetof(struct _cffi_freeme_s, alignment) + (size_t)datasize);
|
| 334 |
+
if (fp == NULL)
|
| 335 |
+
return -1;
|
| 336 |
+
fp->next = *freeme;
|
| 337 |
+
*freeme = fp;
|
| 338 |
+
p = *output_data = (char *)&fp->alignment;
|
| 339 |
+
}
|
| 340 |
+
memset((void *)p, 0, (size_t)datasize);
|
| 341 |
+
return _cffi_convert_array_from_object(p, ctptr, arg);
|
| 342 |
+
}
|
| 343 |
+
|
| 344 |
+
_CFFI_UNUSED_FN static void
|
| 345 |
+
_cffi_free_array_arguments(struct _cffi_freeme_s *freeme)
|
| 346 |
+
{
|
| 347 |
+
do {
|
| 348 |
+
void *p = (void *)freeme;
|
| 349 |
+
freeme = freeme->next;
|
| 350 |
+
PyObject_Free(p);
|
| 351 |
+
} while (freeme != NULL);
|
| 352 |
+
}
|
| 353 |
+
|
| 354 |
+
/********** end CPython-specific section **********/
|
| 355 |
+
#else
|
| 356 |
+
_CFFI_UNUSED_FN
|
| 357 |
+
static void (*_cffi_call_python_org)(struct _cffi_externpy_s *, char *);
|
| 358 |
+
# define _cffi_call_python _cffi_call_python_org
|
| 359 |
+
#endif
|
| 360 |
+
|
| 361 |
+
|
| 362 |
+
#define _cffi_array_len(array) (sizeof(array) / sizeof((array)[0]))
|
| 363 |
+
|
| 364 |
+
#define _cffi_prim_int(size, sign) \
|
| 365 |
+
((size) == 1 ? ((sign) ? _CFFI_PRIM_INT8 : _CFFI_PRIM_UINT8) : \
|
| 366 |
+
(size) == 2 ? ((sign) ? _CFFI_PRIM_INT16 : _CFFI_PRIM_UINT16) : \
|
| 367 |
+
(size) == 4 ? ((sign) ? _CFFI_PRIM_INT32 : _CFFI_PRIM_UINT32) : \
|
| 368 |
+
(size) == 8 ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) : \
|
| 369 |
+
_CFFI__UNKNOWN_PRIM)
|
| 370 |
+
|
| 371 |
+
#define _cffi_prim_float(size) \
|
| 372 |
+
((size) == sizeof(float) ? _CFFI_PRIM_FLOAT : \
|
| 373 |
+
(size) == sizeof(double) ? _CFFI_PRIM_DOUBLE : \
|
| 374 |
+
(size) == sizeof(long double) ? _CFFI__UNKNOWN_LONG_DOUBLE : \
|
| 375 |
+
_CFFI__UNKNOWN_FLOAT_PRIM)
|
| 376 |
+
|
| 377 |
+
#define _cffi_check_int(got, got_nonpos, expected) \
|
| 378 |
+
((got_nonpos) == (expected <= 0) && \
|
| 379 |
+
(got) == (unsigned long long)expected)
|
| 380 |
+
|
| 381 |
+
#ifdef MS_WIN32
|
| 382 |
+
# define _cffi_stdcall __stdcall
|
| 383 |
+
#else
|
| 384 |
+
# define _cffi_stdcall /* nothing */
|
| 385 |
+
#endif
|
| 386 |
+
|
| 387 |
+
#ifdef __cplusplus
|
| 388 |
+
}
|
| 389 |
+
#endif
|
.venv/lib/python3.12/site-packages/cffi/_embedding.h
ADDED
|
@@ -0,0 +1,550 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
/***** Support code for embedding *****/
|
| 3 |
+
|
| 4 |
+
#ifdef __cplusplus
|
| 5 |
+
extern "C" {
|
| 6 |
+
#endif
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
#if defined(_WIN32)
|
| 10 |
+
# define CFFI_DLLEXPORT __declspec(dllexport)
|
| 11 |
+
#elif defined(__GNUC__)
|
| 12 |
+
# define CFFI_DLLEXPORT __attribute__((visibility("default")))
|
| 13 |
+
#else
|
| 14 |
+
# define CFFI_DLLEXPORT /* nothing */
|
| 15 |
+
#endif
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
/* There are two global variables of type _cffi_call_python_fnptr:
|
| 19 |
+
|
| 20 |
+
* _cffi_call_python, which we declare just below, is the one called
|
| 21 |
+
by ``extern "Python"`` implementations.
|
| 22 |
+
|
| 23 |
+
* _cffi_call_python_org, which on CPython is actually part of the
|
| 24 |
+
_cffi_exports[] array, is the function pointer copied from
|
| 25 |
+
_cffi_backend. If _cffi_start_python() fails, then this is set
|
| 26 |
+
to NULL; otherwise, it should never be NULL.
|
| 27 |
+
|
| 28 |
+
After initialization is complete, both are equal. However, the
|
| 29 |
+
first one remains equal to &_cffi_start_and_call_python until the
|
| 30 |
+
very end of initialization, when we are (or should be) sure that
|
| 31 |
+
concurrent threads also see a completely initialized world, and
|
| 32 |
+
only then is it changed.
|
| 33 |
+
*/
|
| 34 |
+
#undef _cffi_call_python
|
| 35 |
+
typedef void (*_cffi_call_python_fnptr)(struct _cffi_externpy_s *, char *);
|
| 36 |
+
static void _cffi_start_and_call_python(struct _cffi_externpy_s *, char *);
|
| 37 |
+
static _cffi_call_python_fnptr _cffi_call_python = &_cffi_start_and_call_python;
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
#ifndef _MSC_VER
|
| 41 |
+
/* --- Assuming a GCC not infinitely old --- */
|
| 42 |
+
# define cffi_compare_and_swap(l,o,n) __sync_bool_compare_and_swap(l,o,n)
|
| 43 |
+
# define cffi_write_barrier() __sync_synchronize()
|
| 44 |
+
# if !defined(__amd64__) && !defined(__x86_64__) && \
|
| 45 |
+
!defined(__i386__) && !defined(__i386)
|
| 46 |
+
# define cffi_read_barrier() __sync_synchronize()
|
| 47 |
+
# else
|
| 48 |
+
# define cffi_read_barrier() (void)0
|
| 49 |
+
# endif
|
| 50 |
+
#else
|
| 51 |
+
/* --- Windows threads version --- */
|
| 52 |
+
# include <Windows.h>
|
| 53 |
+
# define cffi_compare_and_swap(l,o,n) \
|
| 54 |
+
(InterlockedCompareExchangePointer(l,n,o) == (o))
|
| 55 |
+
# define cffi_write_barrier() InterlockedCompareExchange(&_cffi_dummy,0,0)
|
| 56 |
+
# define cffi_read_barrier() (void)0
|
| 57 |
+
static volatile LONG _cffi_dummy;
|
| 58 |
+
#endif
|
| 59 |
+
|
| 60 |
+
#ifdef WITH_THREAD
|
| 61 |
+
# ifndef _MSC_VER
|
| 62 |
+
# include <pthread.h>
|
| 63 |
+
static pthread_mutex_t _cffi_embed_startup_lock;
|
| 64 |
+
# else
|
| 65 |
+
static CRITICAL_SECTION _cffi_embed_startup_lock;
|
| 66 |
+
# endif
|
| 67 |
+
static char _cffi_embed_startup_lock_ready = 0;
|
| 68 |
+
#endif
|
| 69 |
+
|
| 70 |
+
static void _cffi_acquire_reentrant_mutex(void)
|
| 71 |
+
{
|
| 72 |
+
static void *volatile lock = NULL;
|
| 73 |
+
|
| 74 |
+
while (!cffi_compare_and_swap(&lock, NULL, (void *)1)) {
|
| 75 |
+
/* should ideally do a spin loop instruction here, but
|
| 76 |
+
hard to do it portably and doesn't really matter I
|
| 77 |
+
think: pthread_mutex_init() should be very fast, and
|
| 78 |
+
this is only run at start-up anyway. */
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
#ifdef WITH_THREAD
|
| 82 |
+
if (!_cffi_embed_startup_lock_ready) {
|
| 83 |
+
# ifndef _MSC_VER
|
| 84 |
+
pthread_mutexattr_t attr;
|
| 85 |
+
pthread_mutexattr_init(&attr);
|
| 86 |
+
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
| 87 |
+
pthread_mutex_init(&_cffi_embed_startup_lock, &attr);
|
| 88 |
+
# else
|
| 89 |
+
InitializeCriticalSection(&_cffi_embed_startup_lock);
|
| 90 |
+
# endif
|
| 91 |
+
_cffi_embed_startup_lock_ready = 1;
|
| 92 |
+
}
|
| 93 |
+
#endif
|
| 94 |
+
|
| 95 |
+
while (!cffi_compare_and_swap(&lock, (void *)1, NULL))
|
| 96 |
+
;
|
| 97 |
+
|
| 98 |
+
#ifndef _MSC_VER
|
| 99 |
+
pthread_mutex_lock(&_cffi_embed_startup_lock);
|
| 100 |
+
#else
|
| 101 |
+
EnterCriticalSection(&_cffi_embed_startup_lock);
|
| 102 |
+
#endif
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
static void _cffi_release_reentrant_mutex(void)
|
| 106 |
+
{
|
| 107 |
+
#ifndef _MSC_VER
|
| 108 |
+
pthread_mutex_unlock(&_cffi_embed_startup_lock);
|
| 109 |
+
#else
|
| 110 |
+
LeaveCriticalSection(&_cffi_embed_startup_lock);
|
| 111 |
+
#endif
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
/********** CPython-specific section **********/
|
| 116 |
+
#ifndef PYPY_VERSION
|
| 117 |
+
|
| 118 |
+
#include "_cffi_errors.h"
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
#define _cffi_call_python_org _cffi_exports[_CFFI_CPIDX]
|
| 122 |
+
|
| 123 |
+
PyMODINIT_FUNC _CFFI_PYTHON_STARTUP_FUNC(void); /* forward */
|
| 124 |
+
|
| 125 |
+
static void _cffi_py_initialize(void)
|
| 126 |
+
{
|
| 127 |
+
/* XXX use initsigs=0, which "skips initialization registration of
|
| 128 |
+
signal handlers, which might be useful when Python is
|
| 129 |
+
embedded" according to the Python docs. But review and think
|
| 130 |
+
if it should be a user-controllable setting.
|
| 131 |
+
|
| 132 |
+
XXX we should also give a way to write errors to a buffer
|
| 133 |
+
instead of to stderr.
|
| 134 |
+
|
| 135 |
+
XXX if importing 'site' fails, CPython (any version) calls
|
| 136 |
+
exit(). Should we try to work around this behavior here?
|
| 137 |
+
*/
|
| 138 |
+
Py_InitializeEx(0);
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
static int _cffi_initialize_python(void)
|
| 142 |
+
{
|
| 143 |
+
/* This initializes Python, imports _cffi_backend, and then the
|
| 144 |
+
present .dll/.so is set up as a CPython C extension module.
|
| 145 |
+
*/
|
| 146 |
+
int result;
|
| 147 |
+
PyGILState_STATE state;
|
| 148 |
+
PyObject *pycode=NULL, *global_dict=NULL, *x;
|
| 149 |
+
PyObject *builtins;
|
| 150 |
+
|
| 151 |
+
state = PyGILState_Ensure();
|
| 152 |
+
|
| 153 |
+
/* Call the initxxx() function from the present module. It will
|
| 154 |
+
create and initialize us as a CPython extension module, instead
|
| 155 |
+
of letting the startup Python code do it---it might reimport
|
| 156 |
+
the same .dll/.so and get maybe confused on some platforms.
|
| 157 |
+
It might also have troubles locating the .dll/.so again for all
|
| 158 |
+
I know.
|
| 159 |
+
*/
|
| 160 |
+
(void)_CFFI_PYTHON_STARTUP_FUNC();
|
| 161 |
+
if (PyErr_Occurred())
|
| 162 |
+
goto error;
|
| 163 |
+
|
| 164 |
+
/* Now run the Python code provided to ffi.embedding_init_code().
|
| 165 |
+
*/
|
| 166 |
+
pycode = Py_CompileString(_CFFI_PYTHON_STARTUP_CODE,
|
| 167 |
+
"<init code for '" _CFFI_MODULE_NAME "'>",
|
| 168 |
+
Py_file_input);
|
| 169 |
+
if (pycode == NULL)
|
| 170 |
+
goto error;
|
| 171 |
+
global_dict = PyDict_New();
|
| 172 |
+
if (global_dict == NULL)
|
| 173 |
+
goto error;
|
| 174 |
+
builtins = PyEval_GetBuiltins();
|
| 175 |
+
if (builtins == NULL)
|
| 176 |
+
goto error;
|
| 177 |
+
if (PyDict_SetItemString(global_dict, "__builtins__", builtins) < 0)
|
| 178 |
+
goto error;
|
| 179 |
+
x = PyEval_EvalCode(
|
| 180 |
+
#if PY_MAJOR_VERSION < 3
|
| 181 |
+
(PyCodeObject *)
|
| 182 |
+
#endif
|
| 183 |
+
pycode, global_dict, global_dict);
|
| 184 |
+
if (x == NULL)
|
| 185 |
+
goto error;
|
| 186 |
+
Py_DECREF(x);
|
| 187 |
+
|
| 188 |
+
/* Done! Now if we've been called from
|
| 189 |
+
_cffi_start_and_call_python() in an ``extern "Python"``, we can
|
| 190 |
+
only hope that the Python code did correctly set up the
|
| 191 |
+
corresponding @ffi.def_extern() function. Otherwise, the
|
| 192 |
+
general logic of ``extern "Python"`` functions (inside the
|
| 193 |
+
_cffi_backend module) will find that the reference is still
|
| 194 |
+
missing and print an error.
|
| 195 |
+
*/
|
| 196 |
+
result = 0;
|
| 197 |
+
done:
|
| 198 |
+
Py_XDECREF(pycode);
|
| 199 |
+
Py_XDECREF(global_dict);
|
| 200 |
+
PyGILState_Release(state);
|
| 201 |
+
return result;
|
| 202 |
+
|
| 203 |
+
error:;
|
| 204 |
+
{
|
| 205 |
+
/* Print as much information as potentially useful.
|
| 206 |
+
Debugging load-time failures with embedding is not fun
|
| 207 |
+
*/
|
| 208 |
+
PyObject *ecap;
|
| 209 |
+
PyObject *exception, *v, *tb, *f, *modules, *mod;
|
| 210 |
+
PyErr_Fetch(&exception, &v, &tb);
|
| 211 |
+
ecap = _cffi_start_error_capture();
|
| 212 |
+
f = PySys_GetObject((char *)"stderr");
|
| 213 |
+
if (f != NULL && f != Py_None) {
|
| 214 |
+
PyFile_WriteString(
|
| 215 |
+
"Failed to initialize the Python-CFFI embedding logic:\n\n", f);
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
if (exception != NULL) {
|
| 219 |
+
PyErr_NormalizeException(&exception, &v, &tb);
|
| 220 |
+
PyErr_Display(exception, v, tb);
|
| 221 |
+
}
|
| 222 |
+
Py_XDECREF(exception);
|
| 223 |
+
Py_XDECREF(v);
|
| 224 |
+
Py_XDECREF(tb);
|
| 225 |
+
|
| 226 |
+
if (f != NULL && f != Py_None) {
|
| 227 |
+
PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
|
| 228 |
+
"\ncompiled with cffi version: 2.0.0"
|
| 229 |
+
"\n_cffi_backend module: ", f);
|
| 230 |
+
modules = PyImport_GetModuleDict();
|
| 231 |
+
mod = PyDict_GetItemString(modules, "_cffi_backend");
|
| 232 |
+
if (mod == NULL) {
|
| 233 |
+
PyFile_WriteString("not loaded", f);
|
| 234 |
+
}
|
| 235 |
+
else {
|
| 236 |
+
v = PyObject_GetAttrString(mod, "__file__");
|
| 237 |
+
PyFile_WriteObject(v, f, 0);
|
| 238 |
+
Py_XDECREF(v);
|
| 239 |
+
}
|
| 240 |
+
PyFile_WriteString("\nsys.path: ", f);
|
| 241 |
+
PyFile_WriteObject(PySys_GetObject((char *)"path"), f, 0);
|
| 242 |
+
PyFile_WriteString("\n\n", f);
|
| 243 |
+
}
|
| 244 |
+
_cffi_stop_error_capture(ecap);
|
| 245 |
+
}
|
| 246 |
+
result = -1;
|
| 247 |
+
goto done;
|
| 248 |
+
}
|
| 249 |
+
|
| 250 |
+
#if PY_VERSION_HEX < 0x03080000
|
| 251 |
+
PyAPI_DATA(char *) _PyParser_TokenNames[]; /* from CPython */
|
| 252 |
+
#endif
|
| 253 |
+
|
| 254 |
+
static int _cffi_carefully_make_gil(void)
|
| 255 |
+
{
|
| 256 |
+
/* This does the basic initialization of Python. It can be called
|
| 257 |
+
completely concurrently from unrelated threads. It assumes
|
| 258 |
+
that we don't hold the GIL before (if it exists), and we don't
|
| 259 |
+
hold it afterwards.
|
| 260 |
+
|
| 261 |
+
(What it really does used to be completely different in Python 2
|
| 262 |
+
and Python 3, with the Python 2 solution avoiding the spin-lock
|
| 263 |
+
around the Py_InitializeEx() call. However, after recent changes
|
| 264 |
+
to CPython 2.7 (issue #358) it no longer works. So we use the
|
| 265 |
+
Python 3 solution everywhere.)
|
| 266 |
+
|
| 267 |
+
This initializes Python by calling Py_InitializeEx().
|
| 268 |
+
Important: this must not be called concurrently at all.
|
| 269 |
+
So we use a global variable as a simple spin lock. This global
|
| 270 |
+
variable must be from 'libpythonX.Y.so', not from this
|
| 271 |
+
cffi-based extension module, because it must be shared from
|
| 272 |
+
different cffi-based extension modules.
|
| 273 |
+
|
| 274 |
+
In Python < 3.8, we choose
|
| 275 |
+
_PyParser_TokenNames[0] as a completely arbitrary pointer value
|
| 276 |
+
that is never written to. The default is to point to the
|
| 277 |
+
string "ENDMARKER". We change it temporarily to point to the
|
| 278 |
+
next character in that string. (Yes, I know it's REALLY
|
| 279 |
+
obscure.)
|
| 280 |
+
|
| 281 |
+
In Python >= 3.8, this string array is no longer writable, so
|
| 282 |
+
instead we pick PyCapsuleType.tp_version_tag. We can't change
|
| 283 |
+
Python < 3.8 because someone might use a mixture of cffi
|
| 284 |
+
embedded modules, some of which were compiled before this file
|
| 285 |
+
changed.
|
| 286 |
+
|
| 287 |
+
In Python >= 3.12, this stopped working because that particular
|
| 288 |
+
tp_version_tag gets modified during interpreter startup. It's
|
| 289 |
+
arguably a bad idea before 3.12 too, but again we can't change
|
| 290 |
+
that because someone might use a mixture of cffi embedded
|
| 291 |
+
modules, and no-one reported a bug so far. In Python >= 3.12
|
| 292 |
+
we go instead for PyCapsuleType.tp_as_buffer, which is supposed
|
| 293 |
+
to always be NULL. We write to it temporarily a pointer to
|
| 294 |
+
a struct full of NULLs, which is semantically the same.
|
| 295 |
+
*/
|
| 296 |
+
|
| 297 |
+
#ifdef WITH_THREAD
|
| 298 |
+
# if PY_VERSION_HEX < 0x03080000
|
| 299 |
+
char *volatile *lock = (char *volatile *)_PyParser_TokenNames;
|
| 300 |
+
char *old_value, *locked_value;
|
| 301 |
+
|
| 302 |
+
while (1) { /* spin loop */
|
| 303 |
+
old_value = *lock;
|
| 304 |
+
locked_value = old_value + 1;
|
| 305 |
+
if (old_value[0] == 'E') {
|
| 306 |
+
assert(old_value[1] == 'N');
|
| 307 |
+
if (cffi_compare_and_swap(lock, old_value, locked_value))
|
| 308 |
+
break;
|
| 309 |
+
}
|
| 310 |
+
else {
|
| 311 |
+
assert(old_value[0] == 'N');
|
| 312 |
+
/* should ideally do a spin loop instruction here, but
|
| 313 |
+
hard to do it portably and doesn't really matter I
|
| 314 |
+
think: PyEval_InitThreads() should be very fast, and
|
| 315 |
+
this is only run at start-up anyway. */
|
| 316 |
+
}
|
| 317 |
+
}
|
| 318 |
+
# else
|
| 319 |
+
# if PY_VERSION_HEX < 0x030C0000
|
| 320 |
+
int volatile *lock = (int volatile *)&PyCapsule_Type.tp_version_tag;
|
| 321 |
+
int old_value, locked_value = -42;
|
| 322 |
+
assert(!(PyCapsule_Type.tp_flags & Py_TPFLAGS_HAVE_VERSION_TAG));
|
| 323 |
+
# else
|
| 324 |
+
static struct ebp_s { PyBufferProcs buf; int mark; } empty_buffer_procs;
|
| 325 |
+
empty_buffer_procs.mark = -42;
|
| 326 |
+
PyBufferProcs *volatile *lock = (PyBufferProcs *volatile *)
|
| 327 |
+
&PyCapsule_Type.tp_as_buffer;
|
| 328 |
+
PyBufferProcs *old_value, *locked_value = &empty_buffer_procs.buf;
|
| 329 |
+
# endif
|
| 330 |
+
|
| 331 |
+
while (1) { /* spin loop */
|
| 332 |
+
old_value = *lock;
|
| 333 |
+
if (old_value == 0) {
|
| 334 |
+
if (cffi_compare_and_swap(lock, old_value, locked_value))
|
| 335 |
+
break;
|
| 336 |
+
}
|
| 337 |
+
else {
|
| 338 |
+
# if PY_VERSION_HEX < 0x030C0000
|
| 339 |
+
assert(old_value == locked_value);
|
| 340 |
+
# else
|
| 341 |
+
/* The pointer should point to a possibly different
|
| 342 |
+
empty_buffer_procs from another C extension module */
|
| 343 |
+
assert(((struct ebp_s *)old_value)->mark == -42);
|
| 344 |
+
# endif
|
| 345 |
+
/* should ideally do a spin loop instruction here, but
|
| 346 |
+
hard to do it portably and doesn't really matter I
|
| 347 |
+
think: PyEval_InitThreads() should be very fast, and
|
| 348 |
+
this is only run at start-up anyway. */
|
| 349 |
+
}
|
| 350 |
+
}
|
| 351 |
+
# endif
|
| 352 |
+
#endif
|
| 353 |
+
|
| 354 |
+
/* call Py_InitializeEx() */
|
| 355 |
+
if (!Py_IsInitialized()) {
|
| 356 |
+
_cffi_py_initialize();
|
| 357 |
+
#if PY_VERSION_HEX < 0x03070000
|
| 358 |
+
PyEval_InitThreads();
|
| 359 |
+
#endif
|
| 360 |
+
PyEval_SaveThread(); /* release the GIL */
|
| 361 |
+
/* the returned tstate must be the one that has been stored into the
|
| 362 |
+
autoTLSkey by _PyGILState_Init() called from Py_Initialize(). */
|
| 363 |
+
}
|
| 364 |
+
else {
|
| 365 |
+
#if PY_VERSION_HEX < 0x03070000
|
| 366 |
+
/* PyEval_InitThreads() is always a no-op from CPython 3.7 */
|
| 367 |
+
PyGILState_STATE state = PyGILState_Ensure();
|
| 368 |
+
PyEval_InitThreads();
|
| 369 |
+
PyGILState_Release(state);
|
| 370 |
+
#endif
|
| 371 |
+
}
|
| 372 |
+
|
| 373 |
+
#ifdef WITH_THREAD
|
| 374 |
+
/* release the lock */
|
| 375 |
+
while (!cffi_compare_and_swap(lock, locked_value, old_value))
|
| 376 |
+
;
|
| 377 |
+
#endif
|
| 378 |
+
|
| 379 |
+
return 0;
|
| 380 |
+
}
|
| 381 |
+
|
| 382 |
+
/********** end CPython-specific section **********/
|
| 383 |
+
|
| 384 |
+
|
| 385 |
+
#else
|
| 386 |
+
|
| 387 |
+
|
| 388 |
+
/********** PyPy-specific section **********/
|
| 389 |
+
|
| 390 |
+
PyMODINIT_FUNC _CFFI_PYTHON_STARTUP_FUNC(const void *[]); /* forward */
|
| 391 |
+
|
| 392 |
+
static struct _cffi_pypy_init_s {
|
| 393 |
+
const char *name;
|
| 394 |
+
void *func; /* function pointer */
|
| 395 |
+
const char *code;
|
| 396 |
+
} _cffi_pypy_init = {
|
| 397 |
+
_CFFI_MODULE_NAME,
|
| 398 |
+
_CFFI_PYTHON_STARTUP_FUNC,
|
| 399 |
+
_CFFI_PYTHON_STARTUP_CODE,
|
| 400 |
+
};
|
| 401 |
+
|
| 402 |
+
extern int pypy_carefully_make_gil(const char *);
|
| 403 |
+
extern int pypy_init_embedded_cffi_module(int, struct _cffi_pypy_init_s *);
|
| 404 |
+
|
| 405 |
+
static int _cffi_carefully_make_gil(void)
|
| 406 |
+
{
|
| 407 |
+
return pypy_carefully_make_gil(_CFFI_MODULE_NAME);
|
| 408 |
+
}
|
| 409 |
+
|
| 410 |
+
static int _cffi_initialize_python(void)
|
| 411 |
+
{
|
| 412 |
+
return pypy_init_embedded_cffi_module(0xB011, &_cffi_pypy_init);
|
| 413 |
+
}
|
| 414 |
+
|
| 415 |
+
/********** end PyPy-specific section **********/
|
| 416 |
+
|
| 417 |
+
|
| 418 |
+
#endif
|
| 419 |
+
|
| 420 |
+
|
| 421 |
+
#ifdef __GNUC__
|
| 422 |
+
__attribute__((noinline))
|
| 423 |
+
#endif
|
| 424 |
+
static _cffi_call_python_fnptr _cffi_start_python(void)
|
| 425 |
+
{
|
| 426 |
+
/* Delicate logic to initialize Python. This function can be
|
| 427 |
+
called multiple times concurrently, e.g. when the process calls
|
| 428 |
+
its first ``extern "Python"`` functions in multiple threads at
|
| 429 |
+
once. It can also be called recursively, in which case we must
|
| 430 |
+
ignore it. We also have to consider what occurs if several
|
| 431 |
+
different cffi-based extensions reach this code in parallel
|
| 432 |
+
threads---it is a different copy of the code, then, and we
|
| 433 |
+
can't have any shared global variable unless it comes from
|
| 434 |
+
'libpythonX.Y.so'.
|
| 435 |
+
|
| 436 |
+
Idea:
|
| 437 |
+
|
| 438 |
+
* _cffi_carefully_make_gil(): "carefully" call
|
| 439 |
+
PyEval_InitThreads() (possibly with Py_InitializeEx() first).
|
| 440 |
+
|
| 441 |
+
* then we use a (local) custom lock to make sure that a call to this
|
| 442 |
+
cffi-based extension will wait if another call to the *same*
|
| 443 |
+
extension is running the initialization in another thread.
|
| 444 |
+
It is reentrant, so that a recursive call will not block, but
|
| 445 |
+
only one from a different thread.
|
| 446 |
+
|
| 447 |
+
* then we grab the GIL and (Python 2) we call Py_InitializeEx().
|
| 448 |
+
At this point, concurrent calls to Py_InitializeEx() are not
|
| 449 |
+
possible: we have the GIL.
|
| 450 |
+
|
| 451 |
+
* do the rest of the specific initialization, which may
|
| 452 |
+
temporarily release the GIL but not the custom lock.
|
| 453 |
+
Only release the custom lock when we are done.
|
| 454 |
+
*/
|
| 455 |
+
static char called = 0;
|
| 456 |
+
|
| 457 |
+
if (_cffi_carefully_make_gil() != 0)
|
| 458 |
+
return NULL;
|
| 459 |
+
|
| 460 |
+
_cffi_acquire_reentrant_mutex();
|
| 461 |
+
|
| 462 |
+
/* Here the GIL exists, but we don't have it. We're only protected
|
| 463 |
+
from concurrency by the reentrant mutex. */
|
| 464 |
+
|
| 465 |
+
/* This file only initializes the embedded module once, the first
|
| 466 |
+
time this is called, even if there are subinterpreters. */
|
| 467 |
+
if (!called) {
|
| 468 |
+
called = 1; /* invoke _cffi_initialize_python() only once,
|
| 469 |
+
but don't set '_cffi_call_python' right now,
|
| 470 |
+
otherwise concurrent threads won't call
|
| 471 |
+
this function at all (we need them to wait) */
|
| 472 |
+
if (_cffi_initialize_python() == 0) {
|
| 473 |
+
/* now initialization is finished. Switch to the fast-path. */
|
| 474 |
+
|
| 475 |
+
/* We would like nobody to see the new value of
|
| 476 |
+
'_cffi_call_python' without also seeing the rest of the
|
| 477 |
+
data initialized. However, this is not possible. But
|
| 478 |
+
the new value of '_cffi_call_python' is the function
|
| 479 |
+
'cffi_call_python()' from _cffi_backend. So: */
|
| 480 |
+
cffi_write_barrier();
|
| 481 |
+
/* ^^^ we put a write barrier here, and a corresponding
|
| 482 |
+
read barrier at the start of cffi_call_python(). This
|
| 483 |
+
ensures that after that read barrier, we see everything
|
| 484 |
+
done here before the write barrier.
|
| 485 |
+
*/
|
| 486 |
+
|
| 487 |
+
assert(_cffi_call_python_org != NULL);
|
| 488 |
+
_cffi_call_python = (_cffi_call_python_fnptr)_cffi_call_python_org;
|
| 489 |
+
}
|
| 490 |
+
else {
|
| 491 |
+
/* initialization failed. Reset this to NULL, even if it was
|
| 492 |
+
already set to some other value. Future calls to
|
| 493 |
+
_cffi_start_python() are still forced to occur, and will
|
| 494 |
+
always return NULL from now on. */
|
| 495 |
+
_cffi_call_python_org = NULL;
|
| 496 |
+
}
|
| 497 |
+
}
|
| 498 |
+
|
| 499 |
+
_cffi_release_reentrant_mutex();
|
| 500 |
+
|
| 501 |
+
return (_cffi_call_python_fnptr)_cffi_call_python_org;
|
| 502 |
+
}
|
| 503 |
+
|
| 504 |
+
static
|
| 505 |
+
void _cffi_start_and_call_python(struct _cffi_externpy_s *externpy, char *args)
|
| 506 |
+
{
|
| 507 |
+
_cffi_call_python_fnptr fnptr;
|
| 508 |
+
int current_err = errno;
|
| 509 |
+
#ifdef _MSC_VER
|
| 510 |
+
int current_lasterr = GetLastError();
|
| 511 |
+
#endif
|
| 512 |
+
fnptr = _cffi_start_python();
|
| 513 |
+
if (fnptr == NULL) {
|
| 514 |
+
fprintf(stderr, "function %s() called, but initialization code "
|
| 515 |
+
"failed. Returning 0.\n", externpy->name);
|
| 516 |
+
memset(args, 0, externpy->size_of_result);
|
| 517 |
+
}
|
| 518 |
+
#ifdef _MSC_VER
|
| 519 |
+
SetLastError(current_lasterr);
|
| 520 |
+
#endif
|
| 521 |
+
errno = current_err;
|
| 522 |
+
|
| 523 |
+
if (fnptr != NULL)
|
| 524 |
+
fnptr(externpy, args);
|
| 525 |
+
}
|
| 526 |
+
|
| 527 |
+
|
| 528 |
+
/* The cffi_start_python() function makes sure Python is initialized
|
| 529 |
+
and our cffi module is set up. It can be called manually from the
|
| 530 |
+
user C code. The same effect is obtained automatically from any
|
| 531 |
+
dll-exported ``extern "Python"`` function. This function returns
|
| 532 |
+
-1 if initialization failed, 0 if all is OK. */
|
| 533 |
+
_CFFI_UNUSED_FN
|
| 534 |
+
static int cffi_start_python(void)
|
| 535 |
+
{
|
| 536 |
+
if (_cffi_call_python == &_cffi_start_and_call_python) {
|
| 537 |
+
if (_cffi_start_python() == NULL)
|
| 538 |
+
return -1;
|
| 539 |
+
}
|
| 540 |
+
cffi_read_barrier();
|
| 541 |
+
return 0;
|
| 542 |
+
}
|
| 543 |
+
|
| 544 |
+
#undef cffi_compare_and_swap
|
| 545 |
+
#undef cffi_write_barrier
|
| 546 |
+
#undef cffi_read_barrier
|
| 547 |
+
|
| 548 |
+
#ifdef __cplusplus
|
| 549 |
+
}
|
| 550 |
+
#endif
|
.venv/lib/python3.12/site-packages/cffi/_imp_emulation.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
try:
|
| 3 |
+
# this works on Python < 3.12
|
| 4 |
+
from imp import *
|
| 5 |
+
|
| 6 |
+
except ImportError:
|
| 7 |
+
# this is a limited emulation for Python >= 3.12.
|
| 8 |
+
# Note that this is used only for tests or for the old ffi.verify().
|
| 9 |
+
# This is copied from the source code of Python 3.11.
|
| 10 |
+
|
| 11 |
+
from _imp import (acquire_lock, release_lock,
|
| 12 |
+
is_builtin, is_frozen)
|
| 13 |
+
|
| 14 |
+
from importlib._bootstrap import _load
|
| 15 |
+
|
| 16 |
+
from importlib import machinery
|
| 17 |
+
import os
|
| 18 |
+
import sys
|
| 19 |
+
import tokenize
|
| 20 |
+
|
| 21 |
+
SEARCH_ERROR = 0
|
| 22 |
+
PY_SOURCE = 1
|
| 23 |
+
PY_COMPILED = 2
|
| 24 |
+
C_EXTENSION = 3
|
| 25 |
+
PY_RESOURCE = 4
|
| 26 |
+
PKG_DIRECTORY = 5
|
| 27 |
+
C_BUILTIN = 6
|
| 28 |
+
PY_FROZEN = 7
|
| 29 |
+
PY_CODERESOURCE = 8
|
| 30 |
+
IMP_HOOK = 9
|
| 31 |
+
|
| 32 |
+
def get_suffixes():
|
| 33 |
+
extensions = [(s, 'rb', C_EXTENSION)
|
| 34 |
+
for s in machinery.EXTENSION_SUFFIXES]
|
| 35 |
+
source = [(s, 'r', PY_SOURCE) for s in machinery.SOURCE_SUFFIXES]
|
| 36 |
+
bytecode = [(s, 'rb', PY_COMPILED) for s in machinery.BYTECODE_SUFFIXES]
|
| 37 |
+
return extensions + source + bytecode
|
| 38 |
+
|
| 39 |
+
def find_module(name, path=None):
|
| 40 |
+
if not isinstance(name, str):
|
| 41 |
+
raise TypeError("'name' must be a str, not {}".format(type(name)))
|
| 42 |
+
elif not isinstance(path, (type(None), list)):
|
| 43 |
+
# Backwards-compatibility
|
| 44 |
+
raise RuntimeError("'path' must be None or a list, "
|
| 45 |
+
"not {}".format(type(path)))
|
| 46 |
+
|
| 47 |
+
if path is None:
|
| 48 |
+
if is_builtin(name):
|
| 49 |
+
return None, None, ('', '', C_BUILTIN)
|
| 50 |
+
elif is_frozen(name):
|
| 51 |
+
return None, None, ('', '', PY_FROZEN)
|
| 52 |
+
else:
|
| 53 |
+
path = sys.path
|
| 54 |
+
|
| 55 |
+
for entry in path:
|
| 56 |
+
package_directory = os.path.join(entry, name)
|
| 57 |
+
for suffix in ['.py', machinery.BYTECODE_SUFFIXES[0]]:
|
| 58 |
+
package_file_name = '__init__' + suffix
|
| 59 |
+
file_path = os.path.join(package_directory, package_file_name)
|
| 60 |
+
if os.path.isfile(file_path):
|
| 61 |
+
return None, package_directory, ('', '', PKG_DIRECTORY)
|
| 62 |
+
for suffix, mode, type_ in get_suffixes():
|
| 63 |
+
file_name = name + suffix
|
| 64 |
+
file_path = os.path.join(entry, file_name)
|
| 65 |
+
if os.path.isfile(file_path):
|
| 66 |
+
break
|
| 67 |
+
else:
|
| 68 |
+
continue
|
| 69 |
+
break # Break out of outer loop when breaking out of inner loop.
|
| 70 |
+
else:
|
| 71 |
+
raise ImportError(name, name=name)
|
| 72 |
+
|
| 73 |
+
encoding = None
|
| 74 |
+
if 'b' not in mode:
|
| 75 |
+
with open(file_path, 'rb') as file:
|
| 76 |
+
encoding = tokenize.detect_encoding(file.readline)[0]
|
| 77 |
+
file = open(file_path, mode, encoding=encoding)
|
| 78 |
+
return file, file_path, (suffix, mode, type_)
|
| 79 |
+
|
| 80 |
+
def load_dynamic(name, path, file=None):
|
| 81 |
+
loader = machinery.ExtensionFileLoader(name, path)
|
| 82 |
+
spec = machinery.ModuleSpec(name=name, loader=loader, origin=path)
|
| 83 |
+
return _load(spec)
|
.venv/lib/python3.12/site-packages/cffi/_shimmed_dist_utils.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Temporary shim module to indirect the bits of distutils we need from setuptools/distutils while providing useful
|
| 3 |
+
error messages beyond `No module named 'distutils' on Python >= 3.12, or when setuptools' vendored distutils is broken.
|
| 4 |
+
|
| 5 |
+
This is a compromise to avoid a hard-dep on setuptools for Python >= 3.12, since many users don't need runtime compilation support from CFFI.
|
| 6 |
+
"""
|
| 7 |
+
import sys
|
| 8 |
+
|
| 9 |
+
try:
|
| 10 |
+
# import setuptools first; this is the most robust way to ensure its embedded distutils is available
|
| 11 |
+
# (the .pth shim should usually work, but this is even more robust)
|
| 12 |
+
import setuptools
|
| 13 |
+
except Exception as ex:
|
| 14 |
+
if sys.version_info >= (3, 12):
|
| 15 |
+
# Python 3.12 has no built-in distutils to fall back on, so any import problem is fatal
|
| 16 |
+
raise Exception("This CFFI feature requires setuptools on Python >= 3.12. The setuptools module is missing or non-functional.") from ex
|
| 17 |
+
|
| 18 |
+
# silently ignore on older Pythons (support fallback to stdlib distutils where available)
|
| 19 |
+
else:
|
| 20 |
+
del setuptools
|
| 21 |
+
|
| 22 |
+
try:
|
| 23 |
+
# bring in just the bits of distutils we need, whether they really came from setuptools or stdlib-embedded distutils
|
| 24 |
+
from distutils import log, sysconfig
|
| 25 |
+
from distutils.ccompiler import CCompiler
|
| 26 |
+
from distutils.command.build_ext import build_ext
|
| 27 |
+
from distutils.core import Distribution, Extension
|
| 28 |
+
from distutils.dir_util import mkpath
|
| 29 |
+
from distutils.errors import DistutilsSetupError, CompileError, LinkError
|
| 30 |
+
from distutils.log import set_threshold, set_verbosity
|
| 31 |
+
|
| 32 |
+
if sys.platform == 'win32':
|
| 33 |
+
try:
|
| 34 |
+
# FUTURE: msvc9compiler module was removed in setuptools 74; consider removing, as it's only used by an ancient patch in `recompiler`
|
| 35 |
+
from distutils.msvc9compiler import MSVCCompiler
|
| 36 |
+
except ImportError:
|
| 37 |
+
MSVCCompiler = None
|
| 38 |
+
except Exception as ex:
|
| 39 |
+
if sys.version_info >= (3, 12):
|
| 40 |
+
raise Exception("This CFFI feature requires setuptools on Python >= 3.12. Please install the setuptools package.") from ex
|
| 41 |
+
|
| 42 |
+
# anything older, just let the underlying distutils import error fly
|
| 43 |
+
raise Exception("This CFFI feature requires distutils. Please install the distutils or setuptools package.") from ex
|
| 44 |
+
|
| 45 |
+
del sys
|
.venv/lib/python3.12/site-packages/cffi/api.py
ADDED
|
@@ -0,0 +1,967 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys, types
|
| 2 |
+
from .lock import allocate_lock
|
| 3 |
+
from .error import CDefError
|
| 4 |
+
from . import model
|
| 5 |
+
|
| 6 |
+
try:
|
| 7 |
+
callable
|
| 8 |
+
except NameError:
|
| 9 |
+
# Python 3.1
|
| 10 |
+
from collections import Callable
|
| 11 |
+
callable = lambda x: isinstance(x, Callable)
|
| 12 |
+
|
| 13 |
+
try:
|
| 14 |
+
basestring
|
| 15 |
+
except NameError:
|
| 16 |
+
# Python 3.x
|
| 17 |
+
basestring = str
|
| 18 |
+
|
| 19 |
+
_unspecified = object()
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
class FFI(object):
|
| 24 |
+
r'''
|
| 25 |
+
The main top-level class that you instantiate once, or once per module.
|
| 26 |
+
|
| 27 |
+
Example usage:
|
| 28 |
+
|
| 29 |
+
ffi = FFI()
|
| 30 |
+
ffi.cdef("""
|
| 31 |
+
int printf(const char *, ...);
|
| 32 |
+
""")
|
| 33 |
+
|
| 34 |
+
C = ffi.dlopen(None) # standard library
|
| 35 |
+
-or-
|
| 36 |
+
C = ffi.verify() # use a C compiler: verify the decl above is right
|
| 37 |
+
|
| 38 |
+
C.printf("hello, %s!\n", ffi.new("char[]", "world"))
|
| 39 |
+
'''
|
| 40 |
+
|
| 41 |
+
def __init__(self, backend=None):
|
| 42 |
+
"""Create an FFI instance. The 'backend' argument is used to
|
| 43 |
+
select a non-default backend, mostly for tests.
|
| 44 |
+
"""
|
| 45 |
+
if backend is None:
|
| 46 |
+
# You need PyPy (>= 2.0 beta), or a CPython (>= 2.6) with
|
| 47 |
+
# _cffi_backend.so compiled.
|
| 48 |
+
import _cffi_backend as backend
|
| 49 |
+
from . import __version__
|
| 50 |
+
if backend.__version__ != __version__:
|
| 51 |
+
# bad version! Try to be as explicit as possible.
|
| 52 |
+
if hasattr(backend, '__file__'):
|
| 53 |
+
# CPython
|
| 54 |
+
raise Exception("Version mismatch: this is the 'cffi' package version %s, located in %r. When we import the top-level '_cffi_backend' extension module, we get version %s, located in %r. The two versions should be equal; check your installation." % (
|
| 55 |
+
__version__, __file__,
|
| 56 |
+
backend.__version__, backend.__file__))
|
| 57 |
+
else:
|
| 58 |
+
# PyPy
|
| 59 |
+
raise Exception("Version mismatch: this is the 'cffi' package version %s, located in %r. This interpreter comes with a built-in '_cffi_backend' module, which is version %s. The two versions should be equal; check your installation." % (
|
| 60 |
+
__version__, __file__, backend.__version__))
|
| 61 |
+
# (If you insist you can also try to pass the option
|
| 62 |
+
# 'backend=backend_ctypes.CTypesBackend()', but don't
|
| 63 |
+
# rely on it! It's probably not going to work well.)
|
| 64 |
+
|
| 65 |
+
from . import cparser
|
| 66 |
+
self._backend = backend
|
| 67 |
+
self._lock = allocate_lock()
|
| 68 |
+
self._parser = cparser.Parser()
|
| 69 |
+
self._cached_btypes = {}
|
| 70 |
+
self._parsed_types = types.ModuleType('parsed_types').__dict__
|
| 71 |
+
self._new_types = types.ModuleType('new_types').__dict__
|
| 72 |
+
self._function_caches = []
|
| 73 |
+
self._libraries = []
|
| 74 |
+
self._cdefsources = []
|
| 75 |
+
self._included_ffis = []
|
| 76 |
+
self._windows_unicode = None
|
| 77 |
+
self._init_once_cache = {}
|
| 78 |
+
self._cdef_version = None
|
| 79 |
+
self._embedding = None
|
| 80 |
+
self._typecache = model.get_typecache(backend)
|
| 81 |
+
if hasattr(backend, 'set_ffi'):
|
| 82 |
+
backend.set_ffi(self)
|
| 83 |
+
for name in list(backend.__dict__):
|
| 84 |
+
if name.startswith('RTLD_'):
|
| 85 |
+
setattr(self, name, getattr(backend, name))
|
| 86 |
+
#
|
| 87 |
+
with self._lock:
|
| 88 |
+
self.BVoidP = self._get_cached_btype(model.voidp_type)
|
| 89 |
+
self.BCharA = self._get_cached_btype(model.char_array_type)
|
| 90 |
+
if isinstance(backend, types.ModuleType):
|
| 91 |
+
# _cffi_backend: attach these constants to the class
|
| 92 |
+
if not hasattr(FFI, 'NULL'):
|
| 93 |
+
FFI.NULL = self.cast(self.BVoidP, 0)
|
| 94 |
+
FFI.CData, FFI.CType = backend._get_types()
|
| 95 |
+
else:
|
| 96 |
+
# ctypes backend: attach these constants to the instance
|
| 97 |
+
self.NULL = self.cast(self.BVoidP, 0)
|
| 98 |
+
self.CData, self.CType = backend._get_types()
|
| 99 |
+
self.buffer = backend.buffer
|
| 100 |
+
|
| 101 |
+
def cdef(self, csource, override=False, packed=False, pack=None):
|
| 102 |
+
"""Parse the given C source. This registers all declared functions,
|
| 103 |
+
types, and global variables. The functions and global variables can
|
| 104 |
+
then be accessed via either 'ffi.dlopen()' or 'ffi.verify()'.
|
| 105 |
+
The types can be used in 'ffi.new()' and other functions.
|
| 106 |
+
If 'packed' is specified as True, all structs declared inside this
|
| 107 |
+
cdef are packed, i.e. laid out without any field alignment at all.
|
| 108 |
+
Alternatively, 'pack' can be a small integer, and requests for
|
| 109 |
+
alignment greater than that are ignored (pack=1 is equivalent to
|
| 110 |
+
packed=True).
|
| 111 |
+
"""
|
| 112 |
+
self._cdef(csource, override=override, packed=packed, pack=pack)
|
| 113 |
+
|
| 114 |
+
def embedding_api(self, csource, packed=False, pack=None):
|
| 115 |
+
self._cdef(csource, packed=packed, pack=pack, dllexport=True)
|
| 116 |
+
if self._embedding is None:
|
| 117 |
+
self._embedding = ''
|
| 118 |
+
|
| 119 |
+
def _cdef(self, csource, override=False, **options):
|
| 120 |
+
if not isinstance(csource, str): # unicode, on Python 2
|
| 121 |
+
if not isinstance(csource, basestring):
|
| 122 |
+
raise TypeError("cdef() argument must be a string")
|
| 123 |
+
csource = csource.encode('ascii')
|
| 124 |
+
with self._lock:
|
| 125 |
+
self._cdef_version = object()
|
| 126 |
+
self._parser.parse(csource, override=override, **options)
|
| 127 |
+
self._cdefsources.append(csource)
|
| 128 |
+
if override:
|
| 129 |
+
for cache in self._function_caches:
|
| 130 |
+
cache.clear()
|
| 131 |
+
finishlist = self._parser._recomplete
|
| 132 |
+
if finishlist:
|
| 133 |
+
self._parser._recomplete = []
|
| 134 |
+
for tp in finishlist:
|
| 135 |
+
tp.finish_backend_type(self, finishlist)
|
| 136 |
+
|
| 137 |
+
def dlopen(self, name, flags=0):
|
| 138 |
+
"""Load and return a dynamic library identified by 'name'.
|
| 139 |
+
The standard C library can be loaded by passing None.
|
| 140 |
+
Note that functions and types declared by 'ffi.cdef()' are not
|
| 141 |
+
linked to a particular library, just like C headers; in the
|
| 142 |
+
library we only look for the actual (untyped) symbols.
|
| 143 |
+
"""
|
| 144 |
+
if not (isinstance(name, basestring) or
|
| 145 |
+
name is None or
|
| 146 |
+
isinstance(name, self.CData)):
|
| 147 |
+
raise TypeError("dlopen(name): name must be a file name, None, "
|
| 148 |
+
"or an already-opened 'void *' handle")
|
| 149 |
+
with self._lock:
|
| 150 |
+
lib, function_cache = _make_ffi_library(self, name, flags)
|
| 151 |
+
self._function_caches.append(function_cache)
|
| 152 |
+
self._libraries.append(lib)
|
| 153 |
+
return lib
|
| 154 |
+
|
| 155 |
+
def dlclose(self, lib):
|
| 156 |
+
"""Close a library obtained with ffi.dlopen(). After this call,
|
| 157 |
+
access to functions or variables from the library will fail
|
| 158 |
+
(possibly with a segmentation fault).
|
| 159 |
+
"""
|
| 160 |
+
type(lib).__cffi_close__(lib)
|
| 161 |
+
|
| 162 |
+
def _typeof_locked(self, cdecl):
|
| 163 |
+
# call me with the lock!
|
| 164 |
+
key = cdecl
|
| 165 |
+
if key in self._parsed_types:
|
| 166 |
+
return self._parsed_types[key]
|
| 167 |
+
#
|
| 168 |
+
if not isinstance(cdecl, str): # unicode, on Python 2
|
| 169 |
+
cdecl = cdecl.encode('ascii')
|
| 170 |
+
#
|
| 171 |
+
type = self._parser.parse_type(cdecl)
|
| 172 |
+
really_a_function_type = type.is_raw_function
|
| 173 |
+
if really_a_function_type:
|
| 174 |
+
type = type.as_function_pointer()
|
| 175 |
+
btype = self._get_cached_btype(type)
|
| 176 |
+
result = btype, really_a_function_type
|
| 177 |
+
self._parsed_types[key] = result
|
| 178 |
+
return result
|
| 179 |
+
|
| 180 |
+
def _typeof(self, cdecl, consider_function_as_funcptr=False):
|
| 181 |
+
# string -> ctype object
|
| 182 |
+
try:
|
| 183 |
+
result = self._parsed_types[cdecl]
|
| 184 |
+
except KeyError:
|
| 185 |
+
with self._lock:
|
| 186 |
+
result = self._typeof_locked(cdecl)
|
| 187 |
+
#
|
| 188 |
+
btype, really_a_function_type = result
|
| 189 |
+
if really_a_function_type and not consider_function_as_funcptr:
|
| 190 |
+
raise CDefError("the type %r is a function type, not a "
|
| 191 |
+
"pointer-to-function type" % (cdecl,))
|
| 192 |
+
return btype
|
| 193 |
+
|
| 194 |
+
def typeof(self, cdecl):
|
| 195 |
+
"""Parse the C type given as a string and return the
|
| 196 |
+
corresponding <ctype> object.
|
| 197 |
+
It can also be used on 'cdata' instance to get its C type.
|
| 198 |
+
"""
|
| 199 |
+
if isinstance(cdecl, basestring):
|
| 200 |
+
return self._typeof(cdecl)
|
| 201 |
+
if isinstance(cdecl, self.CData):
|
| 202 |
+
return self._backend.typeof(cdecl)
|
| 203 |
+
if isinstance(cdecl, types.BuiltinFunctionType):
|
| 204 |
+
res = _builtin_function_type(cdecl)
|
| 205 |
+
if res is not None:
|
| 206 |
+
return res
|
| 207 |
+
if (isinstance(cdecl, types.FunctionType)
|
| 208 |
+
and hasattr(cdecl, '_cffi_base_type')):
|
| 209 |
+
with self._lock:
|
| 210 |
+
return self._get_cached_btype(cdecl._cffi_base_type)
|
| 211 |
+
raise TypeError(type(cdecl))
|
| 212 |
+
|
| 213 |
+
def sizeof(self, cdecl):
|
| 214 |
+
"""Return the size in bytes of the argument. It can be a
|
| 215 |
+
string naming a C type, or a 'cdata' instance.
|
| 216 |
+
"""
|
| 217 |
+
if isinstance(cdecl, basestring):
|
| 218 |
+
BType = self._typeof(cdecl)
|
| 219 |
+
return self._backend.sizeof(BType)
|
| 220 |
+
else:
|
| 221 |
+
return self._backend.sizeof(cdecl)
|
| 222 |
+
|
| 223 |
+
def alignof(self, cdecl):
|
| 224 |
+
"""Return the natural alignment size in bytes of the C type
|
| 225 |
+
given as a string.
|
| 226 |
+
"""
|
| 227 |
+
if isinstance(cdecl, basestring):
|
| 228 |
+
cdecl = self._typeof(cdecl)
|
| 229 |
+
return self._backend.alignof(cdecl)
|
| 230 |
+
|
| 231 |
+
def offsetof(self, cdecl, *fields_or_indexes):
|
| 232 |
+
"""Return the offset of the named field inside the given
|
| 233 |
+
structure or array, which must be given as a C type name.
|
| 234 |
+
You can give several field names in case of nested structures.
|
| 235 |
+
You can also give numeric values which correspond to array
|
| 236 |
+
items, in case of an array type.
|
| 237 |
+
"""
|
| 238 |
+
if isinstance(cdecl, basestring):
|
| 239 |
+
cdecl = self._typeof(cdecl)
|
| 240 |
+
return self._typeoffsetof(cdecl, *fields_or_indexes)[1]
|
| 241 |
+
|
| 242 |
+
def new(self, cdecl, init=None):
|
| 243 |
+
"""Allocate an instance according to the specified C type and
|
| 244 |
+
return a pointer to it. The specified C type must be either a
|
| 245 |
+
pointer or an array: ``new('X *')`` allocates an X and returns
|
| 246 |
+
a pointer to it, whereas ``new('X[n]')`` allocates an array of
|
| 247 |
+
n X'es and returns an array referencing it (which works
|
| 248 |
+
mostly like a pointer, like in C). You can also use
|
| 249 |
+
``new('X[]', n)`` to allocate an array of a non-constant
|
| 250 |
+
length n.
|
| 251 |
+
|
| 252 |
+
The memory is initialized following the rules of declaring a
|
| 253 |
+
global variable in C: by default it is zero-initialized, but
|
| 254 |
+
an explicit initializer can be given which can be used to
|
| 255 |
+
fill all or part of the memory.
|
| 256 |
+
|
| 257 |
+
When the returned <cdata> object goes out of scope, the memory
|
| 258 |
+
is freed. In other words the returned <cdata> object has
|
| 259 |
+
ownership of the value of type 'cdecl' that it points to. This
|
| 260 |
+
means that the raw data can be used as long as this object is
|
| 261 |
+
kept alive, but must not be used for a longer time. Be careful
|
| 262 |
+
about that when copying the pointer to the memory somewhere
|
| 263 |
+
else, e.g. into another structure.
|
| 264 |
+
"""
|
| 265 |
+
if isinstance(cdecl, basestring):
|
| 266 |
+
cdecl = self._typeof(cdecl)
|
| 267 |
+
return self._backend.newp(cdecl, init)
|
| 268 |
+
|
| 269 |
+
def new_allocator(self, alloc=None, free=None,
|
| 270 |
+
should_clear_after_alloc=True):
|
| 271 |
+
"""Return a new allocator, i.e. a function that behaves like ffi.new()
|
| 272 |
+
but uses the provided low-level 'alloc' and 'free' functions.
|
| 273 |
+
|
| 274 |
+
'alloc' is called with the size as argument. If it returns NULL, a
|
| 275 |
+
MemoryError is raised. 'free' is called with the result of 'alloc'
|
| 276 |
+
as argument. Both can be either Python function or directly C
|
| 277 |
+
functions. If 'free' is None, then no free function is called.
|
| 278 |
+
If both 'alloc' and 'free' are None, the default is used.
|
| 279 |
+
|
| 280 |
+
If 'should_clear_after_alloc' is set to False, then the memory
|
| 281 |
+
returned by 'alloc' is assumed to be already cleared (or you are
|
| 282 |
+
fine with garbage); otherwise CFFI will clear it.
|
| 283 |
+
"""
|
| 284 |
+
compiled_ffi = self._backend.FFI()
|
| 285 |
+
allocator = compiled_ffi.new_allocator(alloc, free,
|
| 286 |
+
should_clear_after_alloc)
|
| 287 |
+
def allocate(cdecl, init=None):
|
| 288 |
+
if isinstance(cdecl, basestring):
|
| 289 |
+
cdecl = self._typeof(cdecl)
|
| 290 |
+
return allocator(cdecl, init)
|
| 291 |
+
return allocate
|
| 292 |
+
|
| 293 |
+
def cast(self, cdecl, source):
|
| 294 |
+
"""Similar to a C cast: returns an instance of the named C
|
| 295 |
+
type initialized with the given 'source'. The source is
|
| 296 |
+
casted between integers or pointers of any type.
|
| 297 |
+
"""
|
| 298 |
+
if isinstance(cdecl, basestring):
|
| 299 |
+
cdecl = self._typeof(cdecl)
|
| 300 |
+
return self._backend.cast(cdecl, source)
|
| 301 |
+
|
| 302 |
+
def string(self, cdata, maxlen=-1):
|
| 303 |
+
"""Return a Python string (or unicode string) from the 'cdata'.
|
| 304 |
+
If 'cdata' is a pointer or array of characters or bytes, returns
|
| 305 |
+
the null-terminated string. The returned string extends until
|
| 306 |
+
the first null character, or at most 'maxlen' characters. If
|
| 307 |
+
'cdata' is an array then 'maxlen' defaults to its length.
|
| 308 |
+
|
| 309 |
+
If 'cdata' is a pointer or array of wchar_t, returns a unicode
|
| 310 |
+
string following the same rules.
|
| 311 |
+
|
| 312 |
+
If 'cdata' is a single character or byte or a wchar_t, returns
|
| 313 |
+
it as a string or unicode string.
|
| 314 |
+
|
| 315 |
+
If 'cdata' is an enum, returns the value of the enumerator as a
|
| 316 |
+
string, or 'NUMBER' if the value is out of range.
|
| 317 |
+
"""
|
| 318 |
+
return self._backend.string(cdata, maxlen)
|
| 319 |
+
|
| 320 |
+
def unpack(self, cdata, length):
|
| 321 |
+
"""Unpack an array of C data of the given length,
|
| 322 |
+
returning a Python string/unicode/list.
|
| 323 |
+
|
| 324 |
+
If 'cdata' is a pointer to 'char', returns a byte string.
|
| 325 |
+
It does not stop at the first null. This is equivalent to:
|
| 326 |
+
ffi.buffer(cdata, length)[:]
|
| 327 |
+
|
| 328 |
+
If 'cdata' is a pointer to 'wchar_t', returns a unicode string.
|
| 329 |
+
'length' is measured in wchar_t's; it is not the size in bytes.
|
| 330 |
+
|
| 331 |
+
If 'cdata' is a pointer to anything else, returns a list of
|
| 332 |
+
'length' items. This is a faster equivalent to:
|
| 333 |
+
[cdata[i] for i in range(length)]
|
| 334 |
+
"""
|
| 335 |
+
return self._backend.unpack(cdata, length)
|
| 336 |
+
|
| 337 |
+
#def buffer(self, cdata, size=-1):
|
| 338 |
+
# """Return a read-write buffer object that references the raw C data
|
| 339 |
+
# pointed to by the given 'cdata'. The 'cdata' must be a pointer or
|
| 340 |
+
# an array. Can be passed to functions expecting a buffer, or directly
|
| 341 |
+
# manipulated with:
|
| 342 |
+
#
|
| 343 |
+
# buf[:] get a copy of it in a regular string, or
|
| 344 |
+
# buf[idx] as a single character
|
| 345 |
+
# buf[:] = ...
|
| 346 |
+
# buf[idx] = ... change the content
|
| 347 |
+
# """
|
| 348 |
+
# note that 'buffer' is a type, set on this instance by __init__
|
| 349 |
+
|
| 350 |
+
def from_buffer(self, cdecl, python_buffer=_unspecified,
|
| 351 |
+
require_writable=False):
|
| 352 |
+
"""Return a cdata of the given type pointing to the data of the
|
| 353 |
+
given Python object, which must support the buffer interface.
|
| 354 |
+
Note that this is not meant to be used on the built-in types
|
| 355 |
+
str or unicode (you can build 'char[]' arrays explicitly)
|
| 356 |
+
but only on objects containing large quantities of raw data
|
| 357 |
+
in some other format, like 'array.array' or numpy arrays.
|
| 358 |
+
|
| 359 |
+
The first argument is optional and default to 'char[]'.
|
| 360 |
+
"""
|
| 361 |
+
if python_buffer is _unspecified:
|
| 362 |
+
cdecl, python_buffer = self.BCharA, cdecl
|
| 363 |
+
elif isinstance(cdecl, basestring):
|
| 364 |
+
cdecl = self._typeof(cdecl)
|
| 365 |
+
return self._backend.from_buffer(cdecl, python_buffer,
|
| 366 |
+
require_writable)
|
| 367 |
+
|
| 368 |
+
def memmove(self, dest, src, n):
|
| 369 |
+
"""ffi.memmove(dest, src, n) copies n bytes of memory from src to dest.
|
| 370 |
+
|
| 371 |
+
Like the C function memmove(), the memory areas may overlap;
|
| 372 |
+
apart from that it behaves like the C function memcpy().
|
| 373 |
+
|
| 374 |
+
'src' can be any cdata ptr or array, or any Python buffer object.
|
| 375 |
+
'dest' can be any cdata ptr or array, or a writable Python buffer
|
| 376 |
+
object. The size to copy, 'n', is always measured in bytes.
|
| 377 |
+
|
| 378 |
+
Unlike other methods, this one supports all Python buffer including
|
| 379 |
+
byte strings and bytearrays---but it still does not support
|
| 380 |
+
non-contiguous buffers.
|
| 381 |
+
"""
|
| 382 |
+
return self._backend.memmove(dest, src, n)
|
| 383 |
+
|
| 384 |
+
def callback(self, cdecl, python_callable=None, error=None, onerror=None):
|
| 385 |
+
"""Return a callback object or a decorator making such a
|
| 386 |
+
callback object. 'cdecl' must name a C function pointer type.
|
| 387 |
+
The callback invokes the specified 'python_callable' (which may
|
| 388 |
+
be provided either directly or via a decorator). Important: the
|
| 389 |
+
callback object must be manually kept alive for as long as the
|
| 390 |
+
callback may be invoked from the C level.
|
| 391 |
+
"""
|
| 392 |
+
def callback_decorator_wrap(python_callable):
|
| 393 |
+
if not callable(python_callable):
|
| 394 |
+
raise TypeError("the 'python_callable' argument "
|
| 395 |
+
"is not callable")
|
| 396 |
+
return self._backend.callback(cdecl, python_callable,
|
| 397 |
+
error, onerror)
|
| 398 |
+
if isinstance(cdecl, basestring):
|
| 399 |
+
cdecl = self._typeof(cdecl, consider_function_as_funcptr=True)
|
| 400 |
+
if python_callable is None:
|
| 401 |
+
return callback_decorator_wrap # decorator mode
|
| 402 |
+
else:
|
| 403 |
+
return callback_decorator_wrap(python_callable) # direct mode
|
| 404 |
+
|
| 405 |
+
def getctype(self, cdecl, replace_with=''):
|
| 406 |
+
"""Return a string giving the C type 'cdecl', which may be itself
|
| 407 |
+
a string or a <ctype> object. If 'replace_with' is given, it gives
|
| 408 |
+
extra text to append (or insert for more complicated C types), like
|
| 409 |
+
a variable name, or '*' to get actually the C type 'pointer-to-cdecl'.
|
| 410 |
+
"""
|
| 411 |
+
if isinstance(cdecl, basestring):
|
| 412 |
+
cdecl = self._typeof(cdecl)
|
| 413 |
+
replace_with = replace_with.strip()
|
| 414 |
+
if (replace_with.startswith('*')
|
| 415 |
+
and '&[' in self._backend.getcname(cdecl, '&')):
|
| 416 |
+
replace_with = '(%s)' % replace_with
|
| 417 |
+
elif replace_with and not replace_with[0] in '[(':
|
| 418 |
+
replace_with = ' ' + replace_with
|
| 419 |
+
return self._backend.getcname(cdecl, replace_with)
|
| 420 |
+
|
| 421 |
+
def gc(self, cdata, destructor, size=0):
|
| 422 |
+
"""Return a new cdata object that points to the same
|
| 423 |
+
data. Later, when this new cdata object is garbage-collected,
|
| 424 |
+
'destructor(old_cdata_object)' will be called.
|
| 425 |
+
|
| 426 |
+
The optional 'size' gives an estimate of the size, used to
|
| 427 |
+
trigger the garbage collection more eagerly. So far only used
|
| 428 |
+
on PyPy. It tells the GC that the returned object keeps alive
|
| 429 |
+
roughly 'size' bytes of external memory.
|
| 430 |
+
"""
|
| 431 |
+
return self._backend.gcp(cdata, destructor, size)
|
| 432 |
+
|
| 433 |
+
def _get_cached_btype(self, type):
|
| 434 |
+
assert self._lock.acquire(False) is False
|
| 435 |
+
# call me with the lock!
|
| 436 |
+
try:
|
| 437 |
+
BType = self._cached_btypes[type]
|
| 438 |
+
except KeyError:
|
| 439 |
+
finishlist = []
|
| 440 |
+
BType = type.get_cached_btype(self, finishlist)
|
| 441 |
+
for type in finishlist:
|
| 442 |
+
type.finish_backend_type(self, finishlist)
|
| 443 |
+
return BType
|
| 444 |
+
|
| 445 |
+
def verify(self, source='', tmpdir=None, **kwargs):
|
| 446 |
+
"""Verify that the current ffi signatures compile on this
|
| 447 |
+
machine, and return a dynamic library object. The dynamic
|
| 448 |
+
library can be used to call functions and access global
|
| 449 |
+
variables declared in this 'ffi'. The library is compiled
|
| 450 |
+
by the C compiler: it gives you C-level API compatibility
|
| 451 |
+
(including calling macros). This is unlike 'ffi.dlopen()',
|
| 452 |
+
which requires binary compatibility in the signatures.
|
| 453 |
+
"""
|
| 454 |
+
from .verifier import Verifier, _caller_dir_pycache
|
| 455 |
+
#
|
| 456 |
+
# If set_unicode(True) was called, insert the UNICODE and
|
| 457 |
+
# _UNICODE macro declarations
|
| 458 |
+
if self._windows_unicode:
|
| 459 |
+
self._apply_windows_unicode(kwargs)
|
| 460 |
+
#
|
| 461 |
+
# Set the tmpdir here, and not in Verifier.__init__: it picks
|
| 462 |
+
# up the caller's directory, which we want to be the caller of
|
| 463 |
+
# ffi.verify(), as opposed to the caller of Veritier().
|
| 464 |
+
tmpdir = tmpdir or _caller_dir_pycache()
|
| 465 |
+
#
|
| 466 |
+
# Make a Verifier() and use it to load the library.
|
| 467 |
+
self.verifier = Verifier(self, source, tmpdir, **kwargs)
|
| 468 |
+
lib = self.verifier.load_library()
|
| 469 |
+
#
|
| 470 |
+
# Save the loaded library for keep-alive purposes, even
|
| 471 |
+
# if the caller doesn't keep it alive itself (it should).
|
| 472 |
+
self._libraries.append(lib)
|
| 473 |
+
return lib
|
| 474 |
+
|
| 475 |
+
def _get_errno(self):
|
| 476 |
+
return self._backend.get_errno()
|
| 477 |
+
def _set_errno(self, errno):
|
| 478 |
+
self._backend.set_errno(errno)
|
| 479 |
+
errno = property(_get_errno, _set_errno, None,
|
| 480 |
+
"the value of 'errno' from/to the C calls")
|
| 481 |
+
|
| 482 |
+
def getwinerror(self, code=-1):
|
| 483 |
+
return self._backend.getwinerror(code)
|
| 484 |
+
|
| 485 |
+
def _pointer_to(self, ctype):
|
| 486 |
+
with self._lock:
|
| 487 |
+
return model.pointer_cache(self, ctype)
|
| 488 |
+
|
| 489 |
+
def addressof(self, cdata, *fields_or_indexes):
|
| 490 |
+
"""Return the address of a <cdata 'struct-or-union'>.
|
| 491 |
+
If 'fields_or_indexes' are given, returns the address of that
|
| 492 |
+
field or array item in the structure or array, recursively in
|
| 493 |
+
case of nested structures.
|
| 494 |
+
"""
|
| 495 |
+
try:
|
| 496 |
+
ctype = self._backend.typeof(cdata)
|
| 497 |
+
except TypeError:
|
| 498 |
+
if '__addressof__' in type(cdata).__dict__:
|
| 499 |
+
return type(cdata).__addressof__(cdata, *fields_or_indexes)
|
| 500 |
+
raise
|
| 501 |
+
if fields_or_indexes:
|
| 502 |
+
ctype, offset = self._typeoffsetof(ctype, *fields_or_indexes)
|
| 503 |
+
else:
|
| 504 |
+
if ctype.kind == "pointer":
|
| 505 |
+
raise TypeError("addressof(pointer)")
|
| 506 |
+
offset = 0
|
| 507 |
+
ctypeptr = self._pointer_to(ctype)
|
| 508 |
+
return self._backend.rawaddressof(ctypeptr, cdata, offset)
|
| 509 |
+
|
| 510 |
+
def _typeoffsetof(self, ctype, field_or_index, *fields_or_indexes):
|
| 511 |
+
ctype, offset = self._backend.typeoffsetof(ctype, field_or_index)
|
| 512 |
+
for field1 in fields_or_indexes:
|
| 513 |
+
ctype, offset1 = self._backend.typeoffsetof(ctype, field1, 1)
|
| 514 |
+
offset += offset1
|
| 515 |
+
return ctype, offset
|
| 516 |
+
|
| 517 |
+
def include(self, ffi_to_include):
|
| 518 |
+
"""Includes the typedefs, structs, unions and enums defined
|
| 519 |
+
in another FFI instance. Usage is similar to a #include in C,
|
| 520 |
+
where a part of the program might include types defined in
|
| 521 |
+
another part for its own usage. Note that the include()
|
| 522 |
+
method has no effect on functions, constants and global
|
| 523 |
+
variables, which must anyway be accessed directly from the
|
| 524 |
+
lib object returned by the original FFI instance.
|
| 525 |
+
"""
|
| 526 |
+
if not isinstance(ffi_to_include, FFI):
|
| 527 |
+
raise TypeError("ffi.include() expects an argument that is also of"
|
| 528 |
+
" type cffi.FFI, not %r" % (
|
| 529 |
+
type(ffi_to_include).__name__,))
|
| 530 |
+
if ffi_to_include is self:
|
| 531 |
+
raise ValueError("self.include(self)")
|
| 532 |
+
with ffi_to_include._lock:
|
| 533 |
+
with self._lock:
|
| 534 |
+
self._parser.include(ffi_to_include._parser)
|
| 535 |
+
self._cdefsources.append('[')
|
| 536 |
+
self._cdefsources.extend(ffi_to_include._cdefsources)
|
| 537 |
+
self._cdefsources.append(']')
|
| 538 |
+
self._included_ffis.append(ffi_to_include)
|
| 539 |
+
|
| 540 |
+
def new_handle(self, x):
|
| 541 |
+
return self._backend.newp_handle(self.BVoidP, x)
|
| 542 |
+
|
| 543 |
+
def from_handle(self, x):
|
| 544 |
+
return self._backend.from_handle(x)
|
| 545 |
+
|
| 546 |
+
def release(self, x):
|
| 547 |
+
self._backend.release(x)
|
| 548 |
+
|
| 549 |
+
def set_unicode(self, enabled_flag):
|
| 550 |
+
"""Windows: if 'enabled_flag' is True, enable the UNICODE and
|
| 551 |
+
_UNICODE defines in C, and declare the types like TCHAR and LPTCSTR
|
| 552 |
+
to be (pointers to) wchar_t. If 'enabled_flag' is False,
|
| 553 |
+
declare these types to be (pointers to) plain 8-bit characters.
|
| 554 |
+
This is mostly for backward compatibility; you usually want True.
|
| 555 |
+
"""
|
| 556 |
+
if self._windows_unicode is not None:
|
| 557 |
+
raise ValueError("set_unicode() can only be called once")
|
| 558 |
+
enabled_flag = bool(enabled_flag)
|
| 559 |
+
if enabled_flag:
|
| 560 |
+
self.cdef("typedef wchar_t TBYTE;"
|
| 561 |
+
"typedef wchar_t TCHAR;"
|
| 562 |
+
"typedef const wchar_t *LPCTSTR;"
|
| 563 |
+
"typedef const wchar_t *PCTSTR;"
|
| 564 |
+
"typedef wchar_t *LPTSTR;"
|
| 565 |
+
"typedef wchar_t *PTSTR;"
|
| 566 |
+
"typedef TBYTE *PTBYTE;"
|
| 567 |
+
"typedef TCHAR *PTCHAR;")
|
| 568 |
+
else:
|
| 569 |
+
self.cdef("typedef char TBYTE;"
|
| 570 |
+
"typedef char TCHAR;"
|
| 571 |
+
"typedef const char *LPCTSTR;"
|
| 572 |
+
"typedef const char *PCTSTR;"
|
| 573 |
+
"typedef char *LPTSTR;"
|
| 574 |
+
"typedef char *PTSTR;"
|
| 575 |
+
"typedef TBYTE *PTBYTE;"
|
| 576 |
+
"typedef TCHAR *PTCHAR;")
|
| 577 |
+
self._windows_unicode = enabled_flag
|
| 578 |
+
|
| 579 |
+
def _apply_windows_unicode(self, kwds):
|
| 580 |
+
defmacros = kwds.get('define_macros', ())
|
| 581 |
+
if not isinstance(defmacros, (list, tuple)):
|
| 582 |
+
raise TypeError("'define_macros' must be a list or tuple")
|
| 583 |
+
defmacros = list(defmacros) + [('UNICODE', '1'),
|
| 584 |
+
('_UNICODE', '1')]
|
| 585 |
+
kwds['define_macros'] = defmacros
|
| 586 |
+
|
| 587 |
+
def _apply_embedding_fix(self, kwds):
|
| 588 |
+
# must include an argument like "-lpython2.7" for the compiler
|
| 589 |
+
def ensure(key, value):
|
| 590 |
+
lst = kwds.setdefault(key, [])
|
| 591 |
+
if value not in lst:
|
| 592 |
+
lst.append(value)
|
| 593 |
+
#
|
| 594 |
+
if '__pypy__' in sys.builtin_module_names:
|
| 595 |
+
import os
|
| 596 |
+
if sys.platform == "win32":
|
| 597 |
+
# we need 'libpypy-c.lib'. Current distributions of
|
| 598 |
+
# pypy (>= 4.1) contain it as 'libs/python27.lib'.
|
| 599 |
+
pythonlib = "python{0[0]}{0[1]}".format(sys.version_info)
|
| 600 |
+
if hasattr(sys, 'prefix'):
|
| 601 |
+
ensure('library_dirs', os.path.join(sys.prefix, 'libs'))
|
| 602 |
+
else:
|
| 603 |
+
# we need 'libpypy-c.{so,dylib}', which should be by
|
| 604 |
+
# default located in 'sys.prefix/bin' for installed
|
| 605 |
+
# systems.
|
| 606 |
+
if sys.version_info < (3,):
|
| 607 |
+
pythonlib = "pypy-c"
|
| 608 |
+
else:
|
| 609 |
+
pythonlib = "pypy3-c"
|
| 610 |
+
if hasattr(sys, 'prefix'):
|
| 611 |
+
ensure('library_dirs', os.path.join(sys.prefix, 'bin'))
|
| 612 |
+
# On uninstalled pypy's, the libpypy-c is typically found in
|
| 613 |
+
# .../pypy/goal/.
|
| 614 |
+
if hasattr(sys, 'prefix'):
|
| 615 |
+
ensure('library_dirs', os.path.join(sys.prefix, 'pypy', 'goal'))
|
| 616 |
+
else:
|
| 617 |
+
if sys.platform == "win32":
|
| 618 |
+
template = "python%d%d"
|
| 619 |
+
if hasattr(sys, 'gettotalrefcount'):
|
| 620 |
+
template += '_d'
|
| 621 |
+
else:
|
| 622 |
+
try:
|
| 623 |
+
import sysconfig
|
| 624 |
+
except ImportError: # 2.6
|
| 625 |
+
from cffi._shimmed_dist_utils import sysconfig
|
| 626 |
+
template = "python%d.%d"
|
| 627 |
+
if sysconfig.get_config_var('DEBUG_EXT'):
|
| 628 |
+
template += sysconfig.get_config_var('DEBUG_EXT')
|
| 629 |
+
pythonlib = (template %
|
| 630 |
+
(sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
|
| 631 |
+
if hasattr(sys, 'abiflags'):
|
| 632 |
+
pythonlib += sys.abiflags
|
| 633 |
+
ensure('libraries', pythonlib)
|
| 634 |
+
if sys.platform == "win32":
|
| 635 |
+
ensure('extra_link_args', '/MANIFEST')
|
| 636 |
+
|
| 637 |
+
def set_source(self, module_name, source, source_extension='.c', **kwds):
|
| 638 |
+
import os
|
| 639 |
+
if hasattr(self, '_assigned_source'):
|
| 640 |
+
raise ValueError("set_source() cannot be called several times "
|
| 641 |
+
"per ffi object")
|
| 642 |
+
if not isinstance(module_name, basestring):
|
| 643 |
+
raise TypeError("'module_name' must be a string")
|
| 644 |
+
if os.sep in module_name or (os.altsep and os.altsep in module_name):
|
| 645 |
+
raise ValueError("'module_name' must not contain '/': use a dotted "
|
| 646 |
+
"name to make a 'package.module' location")
|
| 647 |
+
self._assigned_source = (str(module_name), source,
|
| 648 |
+
source_extension, kwds)
|
| 649 |
+
|
| 650 |
+
def set_source_pkgconfig(self, module_name, pkgconfig_libs, source,
|
| 651 |
+
source_extension='.c', **kwds):
|
| 652 |
+
from . import pkgconfig
|
| 653 |
+
if not isinstance(pkgconfig_libs, list):
|
| 654 |
+
raise TypeError("the pkgconfig_libs argument must be a list "
|
| 655 |
+
"of package names")
|
| 656 |
+
kwds2 = pkgconfig.flags_from_pkgconfig(pkgconfig_libs)
|
| 657 |
+
pkgconfig.merge_flags(kwds, kwds2)
|
| 658 |
+
self.set_source(module_name, source, source_extension, **kwds)
|
| 659 |
+
|
| 660 |
+
def distutils_extension(self, tmpdir='build', verbose=True):
|
| 661 |
+
from cffi._shimmed_dist_utils import mkpath
|
| 662 |
+
from .recompiler import recompile
|
| 663 |
+
#
|
| 664 |
+
if not hasattr(self, '_assigned_source'):
|
| 665 |
+
if hasattr(self, 'verifier'): # fallback, 'tmpdir' ignored
|
| 666 |
+
return self.verifier.get_extension()
|
| 667 |
+
raise ValueError("set_source() must be called before"
|
| 668 |
+
" distutils_extension()")
|
| 669 |
+
module_name, source, source_extension, kwds = self._assigned_source
|
| 670 |
+
if source is None:
|
| 671 |
+
raise TypeError("distutils_extension() is only for C extension "
|
| 672 |
+
"modules, not for dlopen()-style pure Python "
|
| 673 |
+
"modules")
|
| 674 |
+
mkpath(tmpdir)
|
| 675 |
+
ext, updated = recompile(self, module_name,
|
| 676 |
+
source, tmpdir=tmpdir, extradir=tmpdir,
|
| 677 |
+
source_extension=source_extension,
|
| 678 |
+
call_c_compiler=False, **kwds)
|
| 679 |
+
if verbose:
|
| 680 |
+
if updated:
|
| 681 |
+
sys.stderr.write("regenerated: %r\n" % (ext.sources[0],))
|
| 682 |
+
else:
|
| 683 |
+
sys.stderr.write("not modified: %r\n" % (ext.sources[0],))
|
| 684 |
+
return ext
|
| 685 |
+
|
| 686 |
+
def emit_c_code(self, filename):
|
| 687 |
+
from .recompiler import recompile
|
| 688 |
+
#
|
| 689 |
+
if not hasattr(self, '_assigned_source'):
|
| 690 |
+
raise ValueError("set_source() must be called before emit_c_code()")
|
| 691 |
+
module_name, source, source_extension, kwds = self._assigned_source
|
| 692 |
+
if source is None:
|
| 693 |
+
raise TypeError("emit_c_code() is only for C extension modules, "
|
| 694 |
+
"not for dlopen()-style pure Python modules")
|
| 695 |
+
recompile(self, module_name, source,
|
| 696 |
+
c_file=filename, call_c_compiler=False,
|
| 697 |
+
uses_ffiplatform=False, **kwds)
|
| 698 |
+
|
| 699 |
+
def emit_python_code(self, filename):
|
| 700 |
+
from .recompiler import recompile
|
| 701 |
+
#
|
| 702 |
+
if not hasattr(self, '_assigned_source'):
|
| 703 |
+
raise ValueError("set_source() must be called before emit_c_code()")
|
| 704 |
+
module_name, source, source_extension, kwds = self._assigned_source
|
| 705 |
+
if source is not None:
|
| 706 |
+
raise TypeError("emit_python_code() is only for dlopen()-style "
|
| 707 |
+
"pure Python modules, not for C extension modules")
|
| 708 |
+
recompile(self, module_name, source,
|
| 709 |
+
c_file=filename, call_c_compiler=False,
|
| 710 |
+
uses_ffiplatform=False, **kwds)
|
| 711 |
+
|
| 712 |
+
def compile(self, tmpdir='.', verbose=0, target=None, debug=None):
|
| 713 |
+
"""The 'target' argument gives the final file name of the
|
| 714 |
+
compiled DLL. Use '*' to force distutils' choice, suitable for
|
| 715 |
+
regular CPython C API modules. Use a file name ending in '.*'
|
| 716 |
+
to ask for the system's default extension for dynamic libraries
|
| 717 |
+
(.so/.dll/.dylib).
|
| 718 |
+
|
| 719 |
+
The default is '*' when building a non-embedded C API extension,
|
| 720 |
+
and (module_name + '.*') when building an embedded library.
|
| 721 |
+
"""
|
| 722 |
+
from .recompiler import recompile
|
| 723 |
+
#
|
| 724 |
+
if not hasattr(self, '_assigned_source'):
|
| 725 |
+
raise ValueError("set_source() must be called before compile()")
|
| 726 |
+
module_name, source, source_extension, kwds = self._assigned_source
|
| 727 |
+
return recompile(self, module_name, source, tmpdir=tmpdir,
|
| 728 |
+
target=target, source_extension=source_extension,
|
| 729 |
+
compiler_verbose=verbose, debug=debug, **kwds)
|
| 730 |
+
|
| 731 |
+
def init_once(self, func, tag):
|
| 732 |
+
# Read _init_once_cache[tag], which is either (False, lock) if
|
| 733 |
+
# we're calling the function now in some thread, or (True, result).
|
| 734 |
+
# Don't call setdefault() in most cases, to avoid allocating and
|
| 735 |
+
# immediately freeing a lock; but still use setdefaut() to avoid
|
| 736 |
+
# races.
|
| 737 |
+
try:
|
| 738 |
+
x = self._init_once_cache[tag]
|
| 739 |
+
except KeyError:
|
| 740 |
+
x = self._init_once_cache.setdefault(tag, (False, allocate_lock()))
|
| 741 |
+
# Common case: we got (True, result), so we return the result.
|
| 742 |
+
if x[0]:
|
| 743 |
+
return x[1]
|
| 744 |
+
# Else, it's a lock. Acquire it to serialize the following tests.
|
| 745 |
+
with x[1]:
|
| 746 |
+
# Read again from _init_once_cache the current status.
|
| 747 |
+
x = self._init_once_cache[tag]
|
| 748 |
+
if x[0]:
|
| 749 |
+
return x[1]
|
| 750 |
+
# Call the function and store the result back.
|
| 751 |
+
result = func()
|
| 752 |
+
self._init_once_cache[tag] = (True, result)
|
| 753 |
+
return result
|
| 754 |
+
|
| 755 |
+
def embedding_init_code(self, pysource):
|
| 756 |
+
if self._embedding:
|
| 757 |
+
raise ValueError("embedding_init_code() can only be called once")
|
| 758 |
+
# fix 'pysource' before it gets dumped into the C file:
|
| 759 |
+
# - remove empty lines at the beginning, so it starts at "line 1"
|
| 760 |
+
# - dedent, if all non-empty lines are indented
|
| 761 |
+
# - check for SyntaxErrors
|
| 762 |
+
import re
|
| 763 |
+
match = re.match(r'\s*\n', pysource)
|
| 764 |
+
if match:
|
| 765 |
+
pysource = pysource[match.end():]
|
| 766 |
+
lines = pysource.splitlines() or ['']
|
| 767 |
+
prefix = re.match(r'\s*', lines[0]).group()
|
| 768 |
+
for i in range(1, len(lines)):
|
| 769 |
+
line = lines[i]
|
| 770 |
+
if line.rstrip():
|
| 771 |
+
while not line.startswith(prefix):
|
| 772 |
+
prefix = prefix[:-1]
|
| 773 |
+
i = len(prefix)
|
| 774 |
+
lines = [line[i:]+'\n' for line in lines]
|
| 775 |
+
pysource = ''.join(lines)
|
| 776 |
+
#
|
| 777 |
+
compile(pysource, "cffi_init", "exec")
|
| 778 |
+
#
|
| 779 |
+
self._embedding = pysource
|
| 780 |
+
|
| 781 |
+
def def_extern(self, *args, **kwds):
|
| 782 |
+
raise ValueError("ffi.def_extern() is only available on API-mode FFI "
|
| 783 |
+
"objects")
|
| 784 |
+
|
| 785 |
+
def list_types(self):
|
| 786 |
+
"""Returns the user type names known to this FFI instance.
|
| 787 |
+
This returns a tuple containing three lists of names:
|
| 788 |
+
(typedef_names, names_of_structs, names_of_unions)
|
| 789 |
+
"""
|
| 790 |
+
typedefs = []
|
| 791 |
+
structs = []
|
| 792 |
+
unions = []
|
| 793 |
+
for key in self._parser._declarations:
|
| 794 |
+
if key.startswith('typedef '):
|
| 795 |
+
typedefs.append(key[8:])
|
| 796 |
+
elif key.startswith('struct '):
|
| 797 |
+
structs.append(key[7:])
|
| 798 |
+
elif key.startswith('union '):
|
| 799 |
+
unions.append(key[6:])
|
| 800 |
+
typedefs.sort()
|
| 801 |
+
structs.sort()
|
| 802 |
+
unions.sort()
|
| 803 |
+
return (typedefs, structs, unions)
|
| 804 |
+
|
| 805 |
+
|
| 806 |
+
def _load_backend_lib(backend, name, flags):
|
| 807 |
+
import os
|
| 808 |
+
if not isinstance(name, basestring):
|
| 809 |
+
if sys.platform != "win32" or name is not None:
|
| 810 |
+
return backend.load_library(name, flags)
|
| 811 |
+
name = "c" # Windows: load_library(None) fails, but this works
|
| 812 |
+
# on Python 2 (backward compatibility hack only)
|
| 813 |
+
first_error = None
|
| 814 |
+
if '.' in name or '/' in name or os.sep in name:
|
| 815 |
+
try:
|
| 816 |
+
return backend.load_library(name, flags)
|
| 817 |
+
except OSError as e:
|
| 818 |
+
first_error = e
|
| 819 |
+
import ctypes.util
|
| 820 |
+
path = ctypes.util.find_library(name)
|
| 821 |
+
if path is None:
|
| 822 |
+
if name == "c" and sys.platform == "win32" and sys.version_info >= (3,):
|
| 823 |
+
raise OSError("dlopen(None) cannot work on Windows for Python 3 "
|
| 824 |
+
"(see http://bugs.python.org/issue23606)")
|
| 825 |
+
msg = ("ctypes.util.find_library() did not manage "
|
| 826 |
+
"to locate a library called %r" % (name,))
|
| 827 |
+
if first_error is not None:
|
| 828 |
+
msg = "%s. Additionally, %s" % (first_error, msg)
|
| 829 |
+
raise OSError(msg)
|
| 830 |
+
return backend.load_library(path, flags)
|
| 831 |
+
|
| 832 |
+
def _make_ffi_library(ffi, libname, flags):
|
| 833 |
+
backend = ffi._backend
|
| 834 |
+
backendlib = _load_backend_lib(backend, libname, flags)
|
| 835 |
+
#
|
| 836 |
+
def accessor_function(name):
|
| 837 |
+
key = 'function ' + name
|
| 838 |
+
tp, _ = ffi._parser._declarations[key]
|
| 839 |
+
BType = ffi._get_cached_btype(tp)
|
| 840 |
+
value = backendlib.load_function(BType, name)
|
| 841 |
+
library.__dict__[name] = value
|
| 842 |
+
#
|
| 843 |
+
def accessor_variable(name):
|
| 844 |
+
key = 'variable ' + name
|
| 845 |
+
tp, _ = ffi._parser._declarations[key]
|
| 846 |
+
BType = ffi._get_cached_btype(tp)
|
| 847 |
+
read_variable = backendlib.read_variable
|
| 848 |
+
write_variable = backendlib.write_variable
|
| 849 |
+
setattr(FFILibrary, name, property(
|
| 850 |
+
lambda self: read_variable(BType, name),
|
| 851 |
+
lambda self, value: write_variable(BType, name, value)))
|
| 852 |
+
#
|
| 853 |
+
def addressof_var(name):
|
| 854 |
+
try:
|
| 855 |
+
return addr_variables[name]
|
| 856 |
+
except KeyError:
|
| 857 |
+
with ffi._lock:
|
| 858 |
+
if name not in addr_variables:
|
| 859 |
+
key = 'variable ' + name
|
| 860 |
+
tp, _ = ffi._parser._declarations[key]
|
| 861 |
+
BType = ffi._get_cached_btype(tp)
|
| 862 |
+
if BType.kind != 'array':
|
| 863 |
+
BType = model.pointer_cache(ffi, BType)
|
| 864 |
+
p = backendlib.load_function(BType, name)
|
| 865 |
+
addr_variables[name] = p
|
| 866 |
+
return addr_variables[name]
|
| 867 |
+
#
|
| 868 |
+
def accessor_constant(name):
|
| 869 |
+
raise NotImplementedError("non-integer constant '%s' cannot be "
|
| 870 |
+
"accessed from a dlopen() library" % (name,))
|
| 871 |
+
#
|
| 872 |
+
def accessor_int_constant(name):
|
| 873 |
+
library.__dict__[name] = ffi._parser._int_constants[name]
|
| 874 |
+
#
|
| 875 |
+
accessors = {}
|
| 876 |
+
accessors_version = [False]
|
| 877 |
+
addr_variables = {}
|
| 878 |
+
#
|
| 879 |
+
def update_accessors():
|
| 880 |
+
if accessors_version[0] is ffi._cdef_version:
|
| 881 |
+
return
|
| 882 |
+
#
|
| 883 |
+
for key, (tp, _) in ffi._parser._declarations.items():
|
| 884 |
+
if not isinstance(tp, model.EnumType):
|
| 885 |
+
tag, name = key.split(' ', 1)
|
| 886 |
+
if tag == 'function':
|
| 887 |
+
accessors[name] = accessor_function
|
| 888 |
+
elif tag == 'variable':
|
| 889 |
+
accessors[name] = accessor_variable
|
| 890 |
+
elif tag == 'constant':
|
| 891 |
+
accessors[name] = accessor_constant
|
| 892 |
+
else:
|
| 893 |
+
for i, enumname in enumerate(tp.enumerators):
|
| 894 |
+
def accessor_enum(name, tp=tp, i=i):
|
| 895 |
+
tp.check_not_partial()
|
| 896 |
+
library.__dict__[name] = tp.enumvalues[i]
|
| 897 |
+
accessors[enumname] = accessor_enum
|
| 898 |
+
for name in ffi._parser._int_constants:
|
| 899 |
+
accessors.setdefault(name, accessor_int_constant)
|
| 900 |
+
accessors_version[0] = ffi._cdef_version
|
| 901 |
+
#
|
| 902 |
+
def make_accessor(name):
|
| 903 |
+
with ffi._lock:
|
| 904 |
+
if name in library.__dict__ or name in FFILibrary.__dict__:
|
| 905 |
+
return # added by another thread while waiting for the lock
|
| 906 |
+
if name not in accessors:
|
| 907 |
+
update_accessors()
|
| 908 |
+
if name not in accessors:
|
| 909 |
+
raise AttributeError(name)
|
| 910 |
+
accessors[name](name)
|
| 911 |
+
#
|
| 912 |
+
class FFILibrary(object):
|
| 913 |
+
def __getattr__(self, name):
|
| 914 |
+
make_accessor(name)
|
| 915 |
+
return getattr(self, name)
|
| 916 |
+
def __setattr__(self, name, value):
|
| 917 |
+
try:
|
| 918 |
+
property = getattr(self.__class__, name)
|
| 919 |
+
except AttributeError:
|
| 920 |
+
make_accessor(name)
|
| 921 |
+
setattr(self, name, value)
|
| 922 |
+
else:
|
| 923 |
+
property.__set__(self, value)
|
| 924 |
+
def __dir__(self):
|
| 925 |
+
with ffi._lock:
|
| 926 |
+
update_accessors()
|
| 927 |
+
return accessors.keys()
|
| 928 |
+
def __addressof__(self, name):
|
| 929 |
+
if name in library.__dict__:
|
| 930 |
+
return library.__dict__[name]
|
| 931 |
+
if name in FFILibrary.__dict__:
|
| 932 |
+
return addressof_var(name)
|
| 933 |
+
make_accessor(name)
|
| 934 |
+
if name in library.__dict__:
|
| 935 |
+
return library.__dict__[name]
|
| 936 |
+
if name in FFILibrary.__dict__:
|
| 937 |
+
return addressof_var(name)
|
| 938 |
+
raise AttributeError("cffi library has no function or "
|
| 939 |
+
"global variable named '%s'" % (name,))
|
| 940 |
+
def __cffi_close__(self):
|
| 941 |
+
backendlib.close_lib()
|
| 942 |
+
self.__dict__.clear()
|
| 943 |
+
#
|
| 944 |
+
if isinstance(libname, basestring):
|
| 945 |
+
try:
|
| 946 |
+
if not isinstance(libname, str): # unicode, on Python 2
|
| 947 |
+
libname = libname.encode('utf-8')
|
| 948 |
+
FFILibrary.__name__ = 'FFILibrary_%s' % libname
|
| 949 |
+
except UnicodeError:
|
| 950 |
+
pass
|
| 951 |
+
library = FFILibrary()
|
| 952 |
+
return library, library.__dict__
|
| 953 |
+
|
| 954 |
+
def _builtin_function_type(func):
|
| 955 |
+
# a hack to make at least ffi.typeof(builtin_function) work,
|
| 956 |
+
# if the builtin function was obtained by 'vengine_cpy'.
|
| 957 |
+
import sys
|
| 958 |
+
try:
|
| 959 |
+
module = sys.modules[func.__module__]
|
| 960 |
+
ffi = module._cffi_original_ffi
|
| 961 |
+
types_of_builtin_funcs = module._cffi_types_of_builtin_funcs
|
| 962 |
+
tp = types_of_builtin_funcs[func]
|
| 963 |
+
except (KeyError, AttributeError, TypeError):
|
| 964 |
+
return None
|
| 965 |
+
else:
|
| 966 |
+
with ffi._lock:
|
| 967 |
+
return ffi._get_cached_btype(tp)
|
.venv/lib/python3.12/site-packages/cffi/backend_ctypes.py
ADDED
|
@@ -0,0 +1,1121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import ctypes, ctypes.util, operator, sys
|
| 2 |
+
from . import model
|
| 3 |
+
|
| 4 |
+
if sys.version_info < (3,):
|
| 5 |
+
bytechr = chr
|
| 6 |
+
else:
|
| 7 |
+
unicode = str
|
| 8 |
+
long = int
|
| 9 |
+
xrange = range
|
| 10 |
+
bytechr = lambda num: bytes([num])
|
| 11 |
+
|
| 12 |
+
class CTypesType(type):
|
| 13 |
+
pass
|
| 14 |
+
|
| 15 |
+
class CTypesData(object):
|
| 16 |
+
__metaclass__ = CTypesType
|
| 17 |
+
__slots__ = ['__weakref__']
|
| 18 |
+
__name__ = '<cdata>'
|
| 19 |
+
|
| 20 |
+
def __init__(self, *args):
|
| 21 |
+
raise TypeError("cannot instantiate %r" % (self.__class__,))
|
| 22 |
+
|
| 23 |
+
@classmethod
|
| 24 |
+
def _newp(cls, init):
|
| 25 |
+
raise TypeError("expected a pointer or array ctype, got '%s'"
|
| 26 |
+
% (cls._get_c_name(),))
|
| 27 |
+
|
| 28 |
+
@staticmethod
|
| 29 |
+
def _to_ctypes(value):
|
| 30 |
+
raise TypeError
|
| 31 |
+
|
| 32 |
+
@classmethod
|
| 33 |
+
def _arg_to_ctypes(cls, *value):
|
| 34 |
+
try:
|
| 35 |
+
ctype = cls._ctype
|
| 36 |
+
except AttributeError:
|
| 37 |
+
raise TypeError("cannot create an instance of %r" % (cls,))
|
| 38 |
+
if value:
|
| 39 |
+
res = cls._to_ctypes(*value)
|
| 40 |
+
if not isinstance(res, ctype):
|
| 41 |
+
res = cls._ctype(res)
|
| 42 |
+
else:
|
| 43 |
+
res = cls._ctype()
|
| 44 |
+
return res
|
| 45 |
+
|
| 46 |
+
@classmethod
|
| 47 |
+
def _create_ctype_obj(cls, init):
|
| 48 |
+
if init is None:
|
| 49 |
+
return cls._arg_to_ctypes()
|
| 50 |
+
else:
|
| 51 |
+
return cls._arg_to_ctypes(init)
|
| 52 |
+
|
| 53 |
+
@staticmethod
|
| 54 |
+
def _from_ctypes(ctypes_value):
|
| 55 |
+
raise TypeError
|
| 56 |
+
|
| 57 |
+
@classmethod
|
| 58 |
+
def _get_c_name(cls, replace_with=''):
|
| 59 |
+
return cls._reftypename.replace(' &', replace_with)
|
| 60 |
+
|
| 61 |
+
@classmethod
|
| 62 |
+
def _fix_class(cls):
|
| 63 |
+
cls.__name__ = 'CData<%s>' % (cls._get_c_name(),)
|
| 64 |
+
cls.__qualname__ = 'CData<%s>' % (cls._get_c_name(),)
|
| 65 |
+
cls.__module__ = 'ffi'
|
| 66 |
+
|
| 67 |
+
def _get_own_repr(self):
|
| 68 |
+
raise NotImplementedError
|
| 69 |
+
|
| 70 |
+
def _addr_repr(self, address):
|
| 71 |
+
if address == 0:
|
| 72 |
+
return 'NULL'
|
| 73 |
+
else:
|
| 74 |
+
if address < 0:
|
| 75 |
+
address += 1 << (8*ctypes.sizeof(ctypes.c_void_p))
|
| 76 |
+
return '0x%x' % address
|
| 77 |
+
|
| 78 |
+
def __repr__(self, c_name=None):
|
| 79 |
+
own = self._get_own_repr()
|
| 80 |
+
return '<cdata %r %s>' % (c_name or self._get_c_name(), own)
|
| 81 |
+
|
| 82 |
+
def _convert_to_address(self, BClass):
|
| 83 |
+
if BClass is None:
|
| 84 |
+
raise TypeError("cannot convert %r to an address" % (
|
| 85 |
+
self._get_c_name(),))
|
| 86 |
+
else:
|
| 87 |
+
raise TypeError("cannot convert %r to %r" % (
|
| 88 |
+
self._get_c_name(), BClass._get_c_name()))
|
| 89 |
+
|
| 90 |
+
@classmethod
|
| 91 |
+
def _get_size(cls):
|
| 92 |
+
return ctypes.sizeof(cls._ctype)
|
| 93 |
+
|
| 94 |
+
def _get_size_of_instance(self):
|
| 95 |
+
return ctypes.sizeof(self._ctype)
|
| 96 |
+
|
| 97 |
+
@classmethod
|
| 98 |
+
def _cast_from(cls, source):
|
| 99 |
+
raise TypeError("cannot cast to %r" % (cls._get_c_name(),))
|
| 100 |
+
|
| 101 |
+
def _cast_to_integer(self):
|
| 102 |
+
return self._convert_to_address(None)
|
| 103 |
+
|
| 104 |
+
@classmethod
|
| 105 |
+
def _alignment(cls):
|
| 106 |
+
return ctypes.alignment(cls._ctype)
|
| 107 |
+
|
| 108 |
+
def __iter__(self):
|
| 109 |
+
raise TypeError("cdata %r does not support iteration" % (
|
| 110 |
+
self._get_c_name()),)
|
| 111 |
+
|
| 112 |
+
def _make_cmp(name):
|
| 113 |
+
cmpfunc = getattr(operator, name)
|
| 114 |
+
def cmp(self, other):
|
| 115 |
+
v_is_ptr = not isinstance(self, CTypesGenericPrimitive)
|
| 116 |
+
w_is_ptr = (isinstance(other, CTypesData) and
|
| 117 |
+
not isinstance(other, CTypesGenericPrimitive))
|
| 118 |
+
if v_is_ptr and w_is_ptr:
|
| 119 |
+
return cmpfunc(self._convert_to_address(None),
|
| 120 |
+
other._convert_to_address(None))
|
| 121 |
+
elif v_is_ptr or w_is_ptr:
|
| 122 |
+
return NotImplemented
|
| 123 |
+
else:
|
| 124 |
+
if isinstance(self, CTypesGenericPrimitive):
|
| 125 |
+
self = self._value
|
| 126 |
+
if isinstance(other, CTypesGenericPrimitive):
|
| 127 |
+
other = other._value
|
| 128 |
+
return cmpfunc(self, other)
|
| 129 |
+
cmp.func_name = name
|
| 130 |
+
return cmp
|
| 131 |
+
|
| 132 |
+
__eq__ = _make_cmp('__eq__')
|
| 133 |
+
__ne__ = _make_cmp('__ne__')
|
| 134 |
+
__lt__ = _make_cmp('__lt__')
|
| 135 |
+
__le__ = _make_cmp('__le__')
|
| 136 |
+
__gt__ = _make_cmp('__gt__')
|
| 137 |
+
__ge__ = _make_cmp('__ge__')
|
| 138 |
+
|
| 139 |
+
def __hash__(self):
|
| 140 |
+
return hash(self._convert_to_address(None))
|
| 141 |
+
|
| 142 |
+
def _to_string(self, maxlen):
|
| 143 |
+
raise TypeError("string(): %r" % (self,))
|
| 144 |
+
|
| 145 |
+
|
| 146 |
+
class CTypesGenericPrimitive(CTypesData):
|
| 147 |
+
__slots__ = []
|
| 148 |
+
|
| 149 |
+
def __hash__(self):
|
| 150 |
+
return hash(self._value)
|
| 151 |
+
|
| 152 |
+
def _get_own_repr(self):
|
| 153 |
+
return repr(self._from_ctypes(self._value))
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
class CTypesGenericArray(CTypesData):
|
| 157 |
+
__slots__ = []
|
| 158 |
+
|
| 159 |
+
@classmethod
|
| 160 |
+
def _newp(cls, init):
|
| 161 |
+
return cls(init)
|
| 162 |
+
|
| 163 |
+
def __iter__(self):
|
| 164 |
+
for i in xrange(len(self)):
|
| 165 |
+
yield self[i]
|
| 166 |
+
|
| 167 |
+
def _get_own_repr(self):
|
| 168 |
+
return self._addr_repr(ctypes.addressof(self._blob))
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
class CTypesGenericPtr(CTypesData):
|
| 172 |
+
__slots__ = ['_address', '_as_ctype_ptr']
|
| 173 |
+
_automatic_casts = False
|
| 174 |
+
kind = "pointer"
|
| 175 |
+
|
| 176 |
+
@classmethod
|
| 177 |
+
def _newp(cls, init):
|
| 178 |
+
return cls(init)
|
| 179 |
+
|
| 180 |
+
@classmethod
|
| 181 |
+
def _cast_from(cls, source):
|
| 182 |
+
if source is None:
|
| 183 |
+
address = 0
|
| 184 |
+
elif isinstance(source, CTypesData):
|
| 185 |
+
address = source._cast_to_integer()
|
| 186 |
+
elif isinstance(source, (int, long)):
|
| 187 |
+
address = source
|
| 188 |
+
else:
|
| 189 |
+
raise TypeError("bad type for cast to %r: %r" %
|
| 190 |
+
(cls, type(source).__name__))
|
| 191 |
+
return cls._new_pointer_at(address)
|
| 192 |
+
|
| 193 |
+
@classmethod
|
| 194 |
+
def _new_pointer_at(cls, address):
|
| 195 |
+
self = cls.__new__(cls)
|
| 196 |
+
self._address = address
|
| 197 |
+
self._as_ctype_ptr = ctypes.cast(address, cls._ctype)
|
| 198 |
+
return self
|
| 199 |
+
|
| 200 |
+
def _get_own_repr(self):
|
| 201 |
+
try:
|
| 202 |
+
return self._addr_repr(self._address)
|
| 203 |
+
except AttributeError:
|
| 204 |
+
return '???'
|
| 205 |
+
|
| 206 |
+
def _cast_to_integer(self):
|
| 207 |
+
return self._address
|
| 208 |
+
|
| 209 |
+
def __nonzero__(self):
|
| 210 |
+
return bool(self._address)
|
| 211 |
+
__bool__ = __nonzero__
|
| 212 |
+
|
| 213 |
+
@classmethod
|
| 214 |
+
def _to_ctypes(cls, value):
|
| 215 |
+
if not isinstance(value, CTypesData):
|
| 216 |
+
raise TypeError("unexpected %s object" % type(value).__name__)
|
| 217 |
+
address = value._convert_to_address(cls)
|
| 218 |
+
return ctypes.cast(address, cls._ctype)
|
| 219 |
+
|
| 220 |
+
@classmethod
|
| 221 |
+
def _from_ctypes(cls, ctypes_ptr):
|
| 222 |
+
address = ctypes.cast(ctypes_ptr, ctypes.c_void_p).value or 0
|
| 223 |
+
return cls._new_pointer_at(address)
|
| 224 |
+
|
| 225 |
+
@classmethod
|
| 226 |
+
def _initialize(cls, ctypes_ptr, value):
|
| 227 |
+
if value:
|
| 228 |
+
ctypes_ptr.contents = cls._to_ctypes(value).contents
|
| 229 |
+
|
| 230 |
+
def _convert_to_address(self, BClass):
|
| 231 |
+
if (BClass in (self.__class__, None) or BClass._automatic_casts
|
| 232 |
+
or self._automatic_casts):
|
| 233 |
+
return self._address
|
| 234 |
+
else:
|
| 235 |
+
return CTypesData._convert_to_address(self, BClass)
|
| 236 |
+
|
| 237 |
+
|
| 238 |
+
class CTypesBaseStructOrUnion(CTypesData):
|
| 239 |
+
__slots__ = ['_blob']
|
| 240 |
+
|
| 241 |
+
@classmethod
|
| 242 |
+
def _create_ctype_obj(cls, init):
|
| 243 |
+
# may be overridden
|
| 244 |
+
raise TypeError("cannot instantiate opaque type %s" % (cls,))
|
| 245 |
+
|
| 246 |
+
def _get_own_repr(self):
|
| 247 |
+
return self._addr_repr(ctypes.addressof(self._blob))
|
| 248 |
+
|
| 249 |
+
@classmethod
|
| 250 |
+
def _offsetof(cls, fieldname):
|
| 251 |
+
return getattr(cls._ctype, fieldname).offset
|
| 252 |
+
|
| 253 |
+
def _convert_to_address(self, BClass):
|
| 254 |
+
if getattr(BClass, '_BItem', None) is self.__class__:
|
| 255 |
+
return ctypes.addressof(self._blob)
|
| 256 |
+
else:
|
| 257 |
+
return CTypesData._convert_to_address(self, BClass)
|
| 258 |
+
|
| 259 |
+
@classmethod
|
| 260 |
+
def _from_ctypes(cls, ctypes_struct_or_union):
|
| 261 |
+
self = cls.__new__(cls)
|
| 262 |
+
self._blob = ctypes_struct_or_union
|
| 263 |
+
return self
|
| 264 |
+
|
| 265 |
+
@classmethod
|
| 266 |
+
def _to_ctypes(cls, value):
|
| 267 |
+
return value._blob
|
| 268 |
+
|
| 269 |
+
def __repr__(self, c_name=None):
|
| 270 |
+
return CTypesData.__repr__(self, c_name or self._get_c_name(' &'))
|
| 271 |
+
|
| 272 |
+
|
| 273 |
+
class CTypesBackend(object):
|
| 274 |
+
|
| 275 |
+
PRIMITIVE_TYPES = {
|
| 276 |
+
'char': ctypes.c_char,
|
| 277 |
+
'short': ctypes.c_short,
|
| 278 |
+
'int': ctypes.c_int,
|
| 279 |
+
'long': ctypes.c_long,
|
| 280 |
+
'long long': ctypes.c_longlong,
|
| 281 |
+
'signed char': ctypes.c_byte,
|
| 282 |
+
'unsigned char': ctypes.c_ubyte,
|
| 283 |
+
'unsigned short': ctypes.c_ushort,
|
| 284 |
+
'unsigned int': ctypes.c_uint,
|
| 285 |
+
'unsigned long': ctypes.c_ulong,
|
| 286 |
+
'unsigned long long': ctypes.c_ulonglong,
|
| 287 |
+
'float': ctypes.c_float,
|
| 288 |
+
'double': ctypes.c_double,
|
| 289 |
+
'_Bool': ctypes.c_bool,
|
| 290 |
+
}
|
| 291 |
+
|
| 292 |
+
for _name in ['unsigned long long', 'unsigned long',
|
| 293 |
+
'unsigned int', 'unsigned short', 'unsigned char']:
|
| 294 |
+
_size = ctypes.sizeof(PRIMITIVE_TYPES[_name])
|
| 295 |
+
PRIMITIVE_TYPES['uint%d_t' % (8*_size)] = PRIMITIVE_TYPES[_name]
|
| 296 |
+
if _size == ctypes.sizeof(ctypes.c_void_p):
|
| 297 |
+
PRIMITIVE_TYPES['uintptr_t'] = PRIMITIVE_TYPES[_name]
|
| 298 |
+
if _size == ctypes.sizeof(ctypes.c_size_t):
|
| 299 |
+
PRIMITIVE_TYPES['size_t'] = PRIMITIVE_TYPES[_name]
|
| 300 |
+
|
| 301 |
+
for _name in ['long long', 'long', 'int', 'short', 'signed char']:
|
| 302 |
+
_size = ctypes.sizeof(PRIMITIVE_TYPES[_name])
|
| 303 |
+
PRIMITIVE_TYPES['int%d_t' % (8*_size)] = PRIMITIVE_TYPES[_name]
|
| 304 |
+
if _size == ctypes.sizeof(ctypes.c_void_p):
|
| 305 |
+
PRIMITIVE_TYPES['intptr_t'] = PRIMITIVE_TYPES[_name]
|
| 306 |
+
PRIMITIVE_TYPES['ptrdiff_t'] = PRIMITIVE_TYPES[_name]
|
| 307 |
+
if _size == ctypes.sizeof(ctypes.c_size_t):
|
| 308 |
+
PRIMITIVE_TYPES['ssize_t'] = PRIMITIVE_TYPES[_name]
|
| 309 |
+
|
| 310 |
+
|
| 311 |
+
def __init__(self):
|
| 312 |
+
self.RTLD_LAZY = 0 # not supported anyway by ctypes
|
| 313 |
+
self.RTLD_NOW = 0
|
| 314 |
+
self.RTLD_GLOBAL = ctypes.RTLD_GLOBAL
|
| 315 |
+
self.RTLD_LOCAL = ctypes.RTLD_LOCAL
|
| 316 |
+
|
| 317 |
+
def set_ffi(self, ffi):
|
| 318 |
+
self.ffi = ffi
|
| 319 |
+
|
| 320 |
+
def _get_types(self):
|
| 321 |
+
return CTypesData, CTypesType
|
| 322 |
+
|
| 323 |
+
def load_library(self, path, flags=0):
|
| 324 |
+
cdll = ctypes.CDLL(path, flags)
|
| 325 |
+
return CTypesLibrary(self, cdll)
|
| 326 |
+
|
| 327 |
+
def new_void_type(self):
|
| 328 |
+
class CTypesVoid(CTypesData):
|
| 329 |
+
__slots__ = []
|
| 330 |
+
_reftypename = 'void &'
|
| 331 |
+
@staticmethod
|
| 332 |
+
def _from_ctypes(novalue):
|
| 333 |
+
return None
|
| 334 |
+
@staticmethod
|
| 335 |
+
def _to_ctypes(novalue):
|
| 336 |
+
if novalue is not None:
|
| 337 |
+
raise TypeError("None expected, got %s object" %
|
| 338 |
+
(type(novalue).__name__,))
|
| 339 |
+
return None
|
| 340 |
+
CTypesVoid._fix_class()
|
| 341 |
+
return CTypesVoid
|
| 342 |
+
|
| 343 |
+
def new_primitive_type(self, name):
|
| 344 |
+
if name == 'wchar_t':
|
| 345 |
+
raise NotImplementedError(name)
|
| 346 |
+
ctype = self.PRIMITIVE_TYPES[name]
|
| 347 |
+
if name == 'char':
|
| 348 |
+
kind = 'char'
|
| 349 |
+
elif name in ('float', 'double'):
|
| 350 |
+
kind = 'float'
|
| 351 |
+
else:
|
| 352 |
+
if name in ('signed char', 'unsigned char'):
|
| 353 |
+
kind = 'byte'
|
| 354 |
+
elif name == '_Bool':
|
| 355 |
+
kind = 'bool'
|
| 356 |
+
else:
|
| 357 |
+
kind = 'int'
|
| 358 |
+
is_signed = (ctype(-1).value == -1)
|
| 359 |
+
#
|
| 360 |
+
def _cast_source_to_int(source):
|
| 361 |
+
if isinstance(source, (int, long, float)):
|
| 362 |
+
source = int(source)
|
| 363 |
+
elif isinstance(source, CTypesData):
|
| 364 |
+
source = source._cast_to_integer()
|
| 365 |
+
elif isinstance(source, bytes):
|
| 366 |
+
source = ord(source)
|
| 367 |
+
elif source is None:
|
| 368 |
+
source = 0
|
| 369 |
+
else:
|
| 370 |
+
raise TypeError("bad type for cast to %r: %r" %
|
| 371 |
+
(CTypesPrimitive, type(source).__name__))
|
| 372 |
+
return source
|
| 373 |
+
#
|
| 374 |
+
kind1 = kind
|
| 375 |
+
class CTypesPrimitive(CTypesGenericPrimitive):
|
| 376 |
+
__slots__ = ['_value']
|
| 377 |
+
_ctype = ctype
|
| 378 |
+
_reftypename = '%s &' % name
|
| 379 |
+
kind = kind1
|
| 380 |
+
|
| 381 |
+
def __init__(self, value):
|
| 382 |
+
self._value = value
|
| 383 |
+
|
| 384 |
+
@staticmethod
|
| 385 |
+
def _create_ctype_obj(init):
|
| 386 |
+
if init is None:
|
| 387 |
+
return ctype()
|
| 388 |
+
return ctype(CTypesPrimitive._to_ctypes(init))
|
| 389 |
+
|
| 390 |
+
if kind == 'int' or kind == 'byte':
|
| 391 |
+
@classmethod
|
| 392 |
+
def _cast_from(cls, source):
|
| 393 |
+
source = _cast_source_to_int(source)
|
| 394 |
+
source = ctype(source).value # cast within range
|
| 395 |
+
return cls(source)
|
| 396 |
+
def __int__(self):
|
| 397 |
+
return self._value
|
| 398 |
+
|
| 399 |
+
if kind == 'bool':
|
| 400 |
+
@classmethod
|
| 401 |
+
def _cast_from(cls, source):
|
| 402 |
+
if not isinstance(source, (int, long, float)):
|
| 403 |
+
source = _cast_source_to_int(source)
|
| 404 |
+
return cls(bool(source))
|
| 405 |
+
def __int__(self):
|
| 406 |
+
return int(self._value)
|
| 407 |
+
|
| 408 |
+
if kind == 'char':
|
| 409 |
+
@classmethod
|
| 410 |
+
def _cast_from(cls, source):
|
| 411 |
+
source = _cast_source_to_int(source)
|
| 412 |
+
source = bytechr(source & 0xFF)
|
| 413 |
+
return cls(source)
|
| 414 |
+
def __int__(self):
|
| 415 |
+
return ord(self._value)
|
| 416 |
+
|
| 417 |
+
if kind == 'float':
|
| 418 |
+
@classmethod
|
| 419 |
+
def _cast_from(cls, source):
|
| 420 |
+
if isinstance(source, float):
|
| 421 |
+
pass
|
| 422 |
+
elif isinstance(source, CTypesGenericPrimitive):
|
| 423 |
+
if hasattr(source, '__float__'):
|
| 424 |
+
source = float(source)
|
| 425 |
+
else:
|
| 426 |
+
source = int(source)
|
| 427 |
+
else:
|
| 428 |
+
source = _cast_source_to_int(source)
|
| 429 |
+
source = ctype(source).value # fix precision
|
| 430 |
+
return cls(source)
|
| 431 |
+
def __int__(self):
|
| 432 |
+
return int(self._value)
|
| 433 |
+
def __float__(self):
|
| 434 |
+
return self._value
|
| 435 |
+
|
| 436 |
+
_cast_to_integer = __int__
|
| 437 |
+
|
| 438 |
+
if kind == 'int' or kind == 'byte' or kind == 'bool':
|
| 439 |
+
@staticmethod
|
| 440 |
+
def _to_ctypes(x):
|
| 441 |
+
if not isinstance(x, (int, long)):
|
| 442 |
+
if isinstance(x, CTypesData):
|
| 443 |
+
x = int(x)
|
| 444 |
+
else:
|
| 445 |
+
raise TypeError("integer expected, got %s" %
|
| 446 |
+
type(x).__name__)
|
| 447 |
+
if ctype(x).value != x:
|
| 448 |
+
if not is_signed and x < 0:
|
| 449 |
+
raise OverflowError("%s: negative integer" % name)
|
| 450 |
+
else:
|
| 451 |
+
raise OverflowError("%s: integer out of bounds"
|
| 452 |
+
% name)
|
| 453 |
+
return x
|
| 454 |
+
|
| 455 |
+
if kind == 'char':
|
| 456 |
+
@staticmethod
|
| 457 |
+
def _to_ctypes(x):
|
| 458 |
+
if isinstance(x, bytes) and len(x) == 1:
|
| 459 |
+
return x
|
| 460 |
+
if isinstance(x, CTypesPrimitive): # <CData <char>>
|
| 461 |
+
return x._value
|
| 462 |
+
raise TypeError("character expected, got %s" %
|
| 463 |
+
type(x).__name__)
|
| 464 |
+
def __nonzero__(self):
|
| 465 |
+
return ord(self._value) != 0
|
| 466 |
+
else:
|
| 467 |
+
def __nonzero__(self):
|
| 468 |
+
return self._value != 0
|
| 469 |
+
__bool__ = __nonzero__
|
| 470 |
+
|
| 471 |
+
if kind == 'float':
|
| 472 |
+
@staticmethod
|
| 473 |
+
def _to_ctypes(x):
|
| 474 |
+
if not isinstance(x, (int, long, float, CTypesData)):
|
| 475 |
+
raise TypeError("float expected, got %s" %
|
| 476 |
+
type(x).__name__)
|
| 477 |
+
return ctype(x).value
|
| 478 |
+
|
| 479 |
+
@staticmethod
|
| 480 |
+
def _from_ctypes(value):
|
| 481 |
+
return getattr(value, 'value', value)
|
| 482 |
+
|
| 483 |
+
@staticmethod
|
| 484 |
+
def _initialize(blob, init):
|
| 485 |
+
blob.value = CTypesPrimitive._to_ctypes(init)
|
| 486 |
+
|
| 487 |
+
if kind == 'char':
|
| 488 |
+
def _to_string(self, maxlen):
|
| 489 |
+
return self._value
|
| 490 |
+
if kind == 'byte':
|
| 491 |
+
def _to_string(self, maxlen):
|
| 492 |
+
return chr(self._value & 0xff)
|
| 493 |
+
#
|
| 494 |
+
CTypesPrimitive._fix_class()
|
| 495 |
+
return CTypesPrimitive
|
| 496 |
+
|
| 497 |
+
def new_pointer_type(self, BItem):
|
| 498 |
+
getbtype = self.ffi._get_cached_btype
|
| 499 |
+
if BItem is getbtype(model.PrimitiveType('char')):
|
| 500 |
+
kind = 'charp'
|
| 501 |
+
elif BItem in (getbtype(model.PrimitiveType('signed char')),
|
| 502 |
+
getbtype(model.PrimitiveType('unsigned char'))):
|
| 503 |
+
kind = 'bytep'
|
| 504 |
+
elif BItem is getbtype(model.void_type):
|
| 505 |
+
kind = 'voidp'
|
| 506 |
+
else:
|
| 507 |
+
kind = 'generic'
|
| 508 |
+
#
|
| 509 |
+
class CTypesPtr(CTypesGenericPtr):
|
| 510 |
+
__slots__ = ['_own']
|
| 511 |
+
if kind == 'charp':
|
| 512 |
+
__slots__ += ['__as_strbuf']
|
| 513 |
+
_BItem = BItem
|
| 514 |
+
if hasattr(BItem, '_ctype'):
|
| 515 |
+
_ctype = ctypes.POINTER(BItem._ctype)
|
| 516 |
+
_bitem_size = ctypes.sizeof(BItem._ctype)
|
| 517 |
+
else:
|
| 518 |
+
_ctype = ctypes.c_void_p
|
| 519 |
+
if issubclass(BItem, CTypesGenericArray):
|
| 520 |
+
_reftypename = BItem._get_c_name('(* &)')
|
| 521 |
+
else:
|
| 522 |
+
_reftypename = BItem._get_c_name(' * &')
|
| 523 |
+
|
| 524 |
+
def __init__(self, init):
|
| 525 |
+
ctypeobj = BItem._create_ctype_obj(init)
|
| 526 |
+
if kind == 'charp':
|
| 527 |
+
self.__as_strbuf = ctypes.create_string_buffer(
|
| 528 |
+
ctypeobj.value + b'\x00')
|
| 529 |
+
self._as_ctype_ptr = ctypes.cast(
|
| 530 |
+
self.__as_strbuf, self._ctype)
|
| 531 |
+
else:
|
| 532 |
+
self._as_ctype_ptr = ctypes.pointer(ctypeobj)
|
| 533 |
+
self._address = ctypes.cast(self._as_ctype_ptr,
|
| 534 |
+
ctypes.c_void_p).value
|
| 535 |
+
self._own = True
|
| 536 |
+
|
| 537 |
+
def __add__(self, other):
|
| 538 |
+
if isinstance(other, (int, long)):
|
| 539 |
+
return self._new_pointer_at(self._address +
|
| 540 |
+
other * self._bitem_size)
|
| 541 |
+
else:
|
| 542 |
+
return NotImplemented
|
| 543 |
+
|
| 544 |
+
def __sub__(self, other):
|
| 545 |
+
if isinstance(other, (int, long)):
|
| 546 |
+
return self._new_pointer_at(self._address -
|
| 547 |
+
other * self._bitem_size)
|
| 548 |
+
elif type(self) is type(other):
|
| 549 |
+
return (self._address - other._address) // self._bitem_size
|
| 550 |
+
else:
|
| 551 |
+
return NotImplemented
|
| 552 |
+
|
| 553 |
+
def __getitem__(self, index):
|
| 554 |
+
if getattr(self, '_own', False) and index != 0:
|
| 555 |
+
raise IndexError
|
| 556 |
+
return BItem._from_ctypes(self._as_ctype_ptr[index])
|
| 557 |
+
|
| 558 |
+
def __setitem__(self, index, value):
|
| 559 |
+
self._as_ctype_ptr[index] = BItem._to_ctypes(value)
|
| 560 |
+
|
| 561 |
+
if kind == 'charp' or kind == 'voidp':
|
| 562 |
+
@classmethod
|
| 563 |
+
def _arg_to_ctypes(cls, *value):
|
| 564 |
+
if value and isinstance(value[0], bytes):
|
| 565 |
+
return ctypes.c_char_p(value[0])
|
| 566 |
+
else:
|
| 567 |
+
return super(CTypesPtr, cls)._arg_to_ctypes(*value)
|
| 568 |
+
|
| 569 |
+
if kind == 'charp' or kind == 'bytep':
|
| 570 |
+
def _to_string(self, maxlen):
|
| 571 |
+
if maxlen < 0:
|
| 572 |
+
maxlen = sys.maxsize
|
| 573 |
+
p = ctypes.cast(self._as_ctype_ptr,
|
| 574 |
+
ctypes.POINTER(ctypes.c_char))
|
| 575 |
+
n = 0
|
| 576 |
+
while n < maxlen and p[n] != b'\x00':
|
| 577 |
+
n += 1
|
| 578 |
+
return b''.join([p[i] for i in range(n)])
|
| 579 |
+
|
| 580 |
+
def _get_own_repr(self):
|
| 581 |
+
if getattr(self, '_own', False):
|
| 582 |
+
return 'owning %d bytes' % (
|
| 583 |
+
ctypes.sizeof(self._as_ctype_ptr.contents),)
|
| 584 |
+
return super(CTypesPtr, self)._get_own_repr()
|
| 585 |
+
#
|
| 586 |
+
if (BItem is self.ffi._get_cached_btype(model.void_type) or
|
| 587 |
+
BItem is self.ffi._get_cached_btype(model.PrimitiveType('char'))):
|
| 588 |
+
CTypesPtr._automatic_casts = True
|
| 589 |
+
#
|
| 590 |
+
CTypesPtr._fix_class()
|
| 591 |
+
return CTypesPtr
|
| 592 |
+
|
| 593 |
+
def new_array_type(self, CTypesPtr, length):
|
| 594 |
+
if length is None:
|
| 595 |
+
brackets = ' &[]'
|
| 596 |
+
else:
|
| 597 |
+
brackets = ' &[%d]' % length
|
| 598 |
+
BItem = CTypesPtr._BItem
|
| 599 |
+
getbtype = self.ffi._get_cached_btype
|
| 600 |
+
if BItem is getbtype(model.PrimitiveType('char')):
|
| 601 |
+
kind = 'char'
|
| 602 |
+
elif BItem in (getbtype(model.PrimitiveType('signed char')),
|
| 603 |
+
getbtype(model.PrimitiveType('unsigned char'))):
|
| 604 |
+
kind = 'byte'
|
| 605 |
+
else:
|
| 606 |
+
kind = 'generic'
|
| 607 |
+
#
|
| 608 |
+
class CTypesArray(CTypesGenericArray):
|
| 609 |
+
__slots__ = ['_blob', '_own']
|
| 610 |
+
if length is not None:
|
| 611 |
+
_ctype = BItem._ctype * length
|
| 612 |
+
else:
|
| 613 |
+
__slots__.append('_ctype')
|
| 614 |
+
_reftypename = BItem._get_c_name(brackets)
|
| 615 |
+
_declared_length = length
|
| 616 |
+
_CTPtr = CTypesPtr
|
| 617 |
+
|
| 618 |
+
def __init__(self, init):
|
| 619 |
+
if length is None:
|
| 620 |
+
if isinstance(init, (int, long)):
|
| 621 |
+
len1 = init
|
| 622 |
+
init = None
|
| 623 |
+
elif kind == 'char' and isinstance(init, bytes):
|
| 624 |
+
len1 = len(init) + 1 # extra null
|
| 625 |
+
else:
|
| 626 |
+
init = tuple(init)
|
| 627 |
+
len1 = len(init)
|
| 628 |
+
self._ctype = BItem._ctype * len1
|
| 629 |
+
self._blob = self._ctype()
|
| 630 |
+
self._own = True
|
| 631 |
+
if init is not None:
|
| 632 |
+
self._initialize(self._blob, init)
|
| 633 |
+
|
| 634 |
+
@staticmethod
|
| 635 |
+
def _initialize(blob, init):
|
| 636 |
+
if isinstance(init, bytes):
|
| 637 |
+
init = [init[i:i+1] for i in range(len(init))]
|
| 638 |
+
else:
|
| 639 |
+
if isinstance(init, CTypesGenericArray):
|
| 640 |
+
if (len(init) != len(blob) or
|
| 641 |
+
not isinstance(init, CTypesArray)):
|
| 642 |
+
raise TypeError("length/type mismatch: %s" % (init,))
|
| 643 |
+
init = tuple(init)
|
| 644 |
+
if len(init) > len(blob):
|
| 645 |
+
raise IndexError("too many initializers")
|
| 646 |
+
addr = ctypes.cast(blob, ctypes.c_void_p).value
|
| 647 |
+
PTR = ctypes.POINTER(BItem._ctype)
|
| 648 |
+
itemsize = ctypes.sizeof(BItem._ctype)
|
| 649 |
+
for i, value in enumerate(init):
|
| 650 |
+
p = ctypes.cast(addr + i * itemsize, PTR)
|
| 651 |
+
BItem._initialize(p.contents, value)
|
| 652 |
+
|
| 653 |
+
def __len__(self):
|
| 654 |
+
return len(self._blob)
|
| 655 |
+
|
| 656 |
+
def __getitem__(self, index):
|
| 657 |
+
if not (0 <= index < len(self._blob)):
|
| 658 |
+
raise IndexError
|
| 659 |
+
return BItem._from_ctypes(self._blob[index])
|
| 660 |
+
|
| 661 |
+
def __setitem__(self, index, value):
|
| 662 |
+
if not (0 <= index < len(self._blob)):
|
| 663 |
+
raise IndexError
|
| 664 |
+
self._blob[index] = BItem._to_ctypes(value)
|
| 665 |
+
|
| 666 |
+
if kind == 'char' or kind == 'byte':
|
| 667 |
+
def _to_string(self, maxlen):
|
| 668 |
+
if maxlen < 0:
|
| 669 |
+
maxlen = len(self._blob)
|
| 670 |
+
p = ctypes.cast(self._blob,
|
| 671 |
+
ctypes.POINTER(ctypes.c_char))
|
| 672 |
+
n = 0
|
| 673 |
+
while n < maxlen and p[n] != b'\x00':
|
| 674 |
+
n += 1
|
| 675 |
+
return b''.join([p[i] for i in range(n)])
|
| 676 |
+
|
| 677 |
+
def _get_own_repr(self):
|
| 678 |
+
if getattr(self, '_own', False):
|
| 679 |
+
return 'owning %d bytes' % (ctypes.sizeof(self._blob),)
|
| 680 |
+
return super(CTypesArray, self)._get_own_repr()
|
| 681 |
+
|
| 682 |
+
def _convert_to_address(self, BClass):
|
| 683 |
+
if BClass in (CTypesPtr, None) or BClass._automatic_casts:
|
| 684 |
+
return ctypes.addressof(self._blob)
|
| 685 |
+
else:
|
| 686 |
+
return CTypesData._convert_to_address(self, BClass)
|
| 687 |
+
|
| 688 |
+
@staticmethod
|
| 689 |
+
def _from_ctypes(ctypes_array):
|
| 690 |
+
self = CTypesArray.__new__(CTypesArray)
|
| 691 |
+
self._blob = ctypes_array
|
| 692 |
+
return self
|
| 693 |
+
|
| 694 |
+
@staticmethod
|
| 695 |
+
def _arg_to_ctypes(value):
|
| 696 |
+
return CTypesPtr._arg_to_ctypes(value)
|
| 697 |
+
|
| 698 |
+
def __add__(self, other):
|
| 699 |
+
if isinstance(other, (int, long)):
|
| 700 |
+
return CTypesPtr._new_pointer_at(
|
| 701 |
+
ctypes.addressof(self._blob) +
|
| 702 |
+
other * ctypes.sizeof(BItem._ctype))
|
| 703 |
+
else:
|
| 704 |
+
return NotImplemented
|
| 705 |
+
|
| 706 |
+
@classmethod
|
| 707 |
+
def _cast_from(cls, source):
|
| 708 |
+
raise NotImplementedError("casting to %r" % (
|
| 709 |
+
cls._get_c_name(),))
|
| 710 |
+
#
|
| 711 |
+
CTypesArray._fix_class()
|
| 712 |
+
return CTypesArray
|
| 713 |
+
|
| 714 |
+
def _new_struct_or_union(self, kind, name, base_ctypes_class):
|
| 715 |
+
#
|
| 716 |
+
class struct_or_union(base_ctypes_class):
|
| 717 |
+
pass
|
| 718 |
+
struct_or_union.__name__ = '%s_%s' % (kind, name)
|
| 719 |
+
kind1 = kind
|
| 720 |
+
#
|
| 721 |
+
class CTypesStructOrUnion(CTypesBaseStructOrUnion):
|
| 722 |
+
__slots__ = ['_blob']
|
| 723 |
+
_ctype = struct_or_union
|
| 724 |
+
_reftypename = '%s &' % (name,)
|
| 725 |
+
_kind = kind = kind1
|
| 726 |
+
#
|
| 727 |
+
CTypesStructOrUnion._fix_class()
|
| 728 |
+
return CTypesStructOrUnion
|
| 729 |
+
|
| 730 |
+
def new_struct_type(self, name):
|
| 731 |
+
return self._new_struct_or_union('struct', name, ctypes.Structure)
|
| 732 |
+
|
| 733 |
+
def new_union_type(self, name):
|
| 734 |
+
return self._new_struct_or_union('union', name, ctypes.Union)
|
| 735 |
+
|
| 736 |
+
def complete_struct_or_union(self, CTypesStructOrUnion, fields, tp,
|
| 737 |
+
totalsize=-1, totalalignment=-1, sflags=0,
|
| 738 |
+
pack=0):
|
| 739 |
+
if totalsize >= 0 or totalalignment >= 0:
|
| 740 |
+
raise NotImplementedError("the ctypes backend of CFFI does not support "
|
| 741 |
+
"structures completed by verify(); please "
|
| 742 |
+
"compile and install the _cffi_backend module.")
|
| 743 |
+
struct_or_union = CTypesStructOrUnion._ctype
|
| 744 |
+
fnames = [fname for (fname, BField, bitsize) in fields]
|
| 745 |
+
btypes = [BField for (fname, BField, bitsize) in fields]
|
| 746 |
+
bitfields = [bitsize for (fname, BField, bitsize) in fields]
|
| 747 |
+
#
|
| 748 |
+
bfield_types = {}
|
| 749 |
+
cfields = []
|
| 750 |
+
for (fname, BField, bitsize) in fields:
|
| 751 |
+
if bitsize < 0:
|
| 752 |
+
cfields.append((fname, BField._ctype))
|
| 753 |
+
bfield_types[fname] = BField
|
| 754 |
+
else:
|
| 755 |
+
cfields.append((fname, BField._ctype, bitsize))
|
| 756 |
+
bfield_types[fname] = Ellipsis
|
| 757 |
+
if sflags & 8:
|
| 758 |
+
struct_or_union._pack_ = 1
|
| 759 |
+
elif pack:
|
| 760 |
+
struct_or_union._pack_ = pack
|
| 761 |
+
struct_or_union._fields_ = cfields
|
| 762 |
+
CTypesStructOrUnion._bfield_types = bfield_types
|
| 763 |
+
#
|
| 764 |
+
@staticmethod
|
| 765 |
+
def _create_ctype_obj(init):
|
| 766 |
+
result = struct_or_union()
|
| 767 |
+
if init is not None:
|
| 768 |
+
initialize(result, init)
|
| 769 |
+
return result
|
| 770 |
+
CTypesStructOrUnion._create_ctype_obj = _create_ctype_obj
|
| 771 |
+
#
|
| 772 |
+
def initialize(blob, init):
|
| 773 |
+
if is_union:
|
| 774 |
+
if len(init) > 1:
|
| 775 |
+
raise ValueError("union initializer: %d items given, but "
|
| 776 |
+
"only one supported (use a dict if needed)"
|
| 777 |
+
% (len(init),))
|
| 778 |
+
if not isinstance(init, dict):
|
| 779 |
+
if isinstance(init, (bytes, unicode)):
|
| 780 |
+
raise TypeError("union initializer: got a str")
|
| 781 |
+
init = tuple(init)
|
| 782 |
+
if len(init) > len(fnames):
|
| 783 |
+
raise ValueError("too many values for %s initializer" %
|
| 784 |
+
CTypesStructOrUnion._get_c_name())
|
| 785 |
+
init = dict(zip(fnames, init))
|
| 786 |
+
addr = ctypes.addressof(blob)
|
| 787 |
+
for fname, value in init.items():
|
| 788 |
+
BField, bitsize = name2fieldtype[fname]
|
| 789 |
+
assert bitsize < 0, \
|
| 790 |
+
"not implemented: initializer with bit fields"
|
| 791 |
+
offset = CTypesStructOrUnion._offsetof(fname)
|
| 792 |
+
PTR = ctypes.POINTER(BField._ctype)
|
| 793 |
+
p = ctypes.cast(addr + offset, PTR)
|
| 794 |
+
BField._initialize(p.contents, value)
|
| 795 |
+
is_union = CTypesStructOrUnion._kind == 'union'
|
| 796 |
+
name2fieldtype = dict(zip(fnames, zip(btypes, bitfields)))
|
| 797 |
+
#
|
| 798 |
+
for fname, BField, bitsize in fields:
|
| 799 |
+
if fname == '':
|
| 800 |
+
raise NotImplementedError("nested anonymous structs/unions")
|
| 801 |
+
if hasattr(CTypesStructOrUnion, fname):
|
| 802 |
+
raise ValueError("the field name %r conflicts in "
|
| 803 |
+
"the ctypes backend" % fname)
|
| 804 |
+
if bitsize < 0:
|
| 805 |
+
def getter(self, fname=fname, BField=BField,
|
| 806 |
+
offset=CTypesStructOrUnion._offsetof(fname),
|
| 807 |
+
PTR=ctypes.POINTER(BField._ctype)):
|
| 808 |
+
addr = ctypes.addressof(self._blob)
|
| 809 |
+
p = ctypes.cast(addr + offset, PTR)
|
| 810 |
+
return BField._from_ctypes(p.contents)
|
| 811 |
+
def setter(self, value, fname=fname, BField=BField):
|
| 812 |
+
setattr(self._blob, fname, BField._to_ctypes(value))
|
| 813 |
+
#
|
| 814 |
+
if issubclass(BField, CTypesGenericArray):
|
| 815 |
+
setter = None
|
| 816 |
+
if BField._declared_length == 0:
|
| 817 |
+
def getter(self, fname=fname, BFieldPtr=BField._CTPtr,
|
| 818 |
+
offset=CTypesStructOrUnion._offsetof(fname),
|
| 819 |
+
PTR=ctypes.POINTER(BField._ctype)):
|
| 820 |
+
addr = ctypes.addressof(self._blob)
|
| 821 |
+
p = ctypes.cast(addr + offset, PTR)
|
| 822 |
+
return BFieldPtr._from_ctypes(p)
|
| 823 |
+
#
|
| 824 |
+
else:
|
| 825 |
+
def getter(self, fname=fname, BField=BField):
|
| 826 |
+
return BField._from_ctypes(getattr(self._blob, fname))
|
| 827 |
+
def setter(self, value, fname=fname, BField=BField):
|
| 828 |
+
# xxx obscure workaround
|
| 829 |
+
value = BField._to_ctypes(value)
|
| 830 |
+
oldvalue = getattr(self._blob, fname)
|
| 831 |
+
setattr(self._blob, fname, value)
|
| 832 |
+
if value != getattr(self._blob, fname):
|
| 833 |
+
setattr(self._blob, fname, oldvalue)
|
| 834 |
+
raise OverflowError("value too large for bitfield")
|
| 835 |
+
setattr(CTypesStructOrUnion, fname, property(getter, setter))
|
| 836 |
+
#
|
| 837 |
+
CTypesPtr = self.ffi._get_cached_btype(model.PointerType(tp))
|
| 838 |
+
for fname in fnames:
|
| 839 |
+
if hasattr(CTypesPtr, fname):
|
| 840 |
+
raise ValueError("the field name %r conflicts in "
|
| 841 |
+
"the ctypes backend" % fname)
|
| 842 |
+
def getter(self, fname=fname):
|
| 843 |
+
return getattr(self[0], fname)
|
| 844 |
+
def setter(self, value, fname=fname):
|
| 845 |
+
setattr(self[0], fname, value)
|
| 846 |
+
setattr(CTypesPtr, fname, property(getter, setter))
|
| 847 |
+
|
| 848 |
+
def new_function_type(self, BArgs, BResult, has_varargs):
|
| 849 |
+
nameargs = [BArg._get_c_name() for BArg in BArgs]
|
| 850 |
+
if has_varargs:
|
| 851 |
+
nameargs.append('...')
|
| 852 |
+
nameargs = ', '.join(nameargs)
|
| 853 |
+
#
|
| 854 |
+
class CTypesFunctionPtr(CTypesGenericPtr):
|
| 855 |
+
__slots__ = ['_own_callback', '_name']
|
| 856 |
+
_ctype = ctypes.CFUNCTYPE(getattr(BResult, '_ctype', None),
|
| 857 |
+
*[BArg._ctype for BArg in BArgs],
|
| 858 |
+
use_errno=True)
|
| 859 |
+
_reftypename = BResult._get_c_name('(* &)(%s)' % (nameargs,))
|
| 860 |
+
|
| 861 |
+
def __init__(self, init, error=None):
|
| 862 |
+
# create a callback to the Python callable init()
|
| 863 |
+
import traceback
|
| 864 |
+
assert not has_varargs, "varargs not supported for callbacks"
|
| 865 |
+
if getattr(BResult, '_ctype', None) is not None:
|
| 866 |
+
error = BResult._from_ctypes(
|
| 867 |
+
BResult._create_ctype_obj(error))
|
| 868 |
+
else:
|
| 869 |
+
error = None
|
| 870 |
+
def callback(*args):
|
| 871 |
+
args2 = []
|
| 872 |
+
for arg, BArg in zip(args, BArgs):
|
| 873 |
+
args2.append(BArg._from_ctypes(arg))
|
| 874 |
+
try:
|
| 875 |
+
res2 = init(*args2)
|
| 876 |
+
res2 = BResult._to_ctypes(res2)
|
| 877 |
+
except:
|
| 878 |
+
traceback.print_exc()
|
| 879 |
+
res2 = error
|
| 880 |
+
if issubclass(BResult, CTypesGenericPtr):
|
| 881 |
+
if res2:
|
| 882 |
+
res2 = ctypes.cast(res2, ctypes.c_void_p).value
|
| 883 |
+
# .value: http://bugs.python.org/issue1574593
|
| 884 |
+
else:
|
| 885 |
+
res2 = None
|
| 886 |
+
#print repr(res2)
|
| 887 |
+
return res2
|
| 888 |
+
if issubclass(BResult, CTypesGenericPtr):
|
| 889 |
+
# The only pointers callbacks can return are void*s:
|
| 890 |
+
# http://bugs.python.org/issue5710
|
| 891 |
+
callback_ctype = ctypes.CFUNCTYPE(
|
| 892 |
+
ctypes.c_void_p,
|
| 893 |
+
*[BArg._ctype for BArg in BArgs],
|
| 894 |
+
use_errno=True)
|
| 895 |
+
else:
|
| 896 |
+
callback_ctype = CTypesFunctionPtr._ctype
|
| 897 |
+
self._as_ctype_ptr = callback_ctype(callback)
|
| 898 |
+
self._address = ctypes.cast(self._as_ctype_ptr,
|
| 899 |
+
ctypes.c_void_p).value
|
| 900 |
+
self._own_callback = init
|
| 901 |
+
|
| 902 |
+
@staticmethod
|
| 903 |
+
def _initialize(ctypes_ptr, value):
|
| 904 |
+
if value:
|
| 905 |
+
raise NotImplementedError("ctypes backend: not supported: "
|
| 906 |
+
"initializers for function pointers")
|
| 907 |
+
|
| 908 |
+
def __repr__(self):
|
| 909 |
+
c_name = getattr(self, '_name', None)
|
| 910 |
+
if c_name:
|
| 911 |
+
i = self._reftypename.index('(* &)')
|
| 912 |
+
if self._reftypename[i-1] not in ' )*':
|
| 913 |
+
c_name = ' ' + c_name
|
| 914 |
+
c_name = self._reftypename.replace('(* &)', c_name)
|
| 915 |
+
return CTypesData.__repr__(self, c_name)
|
| 916 |
+
|
| 917 |
+
def _get_own_repr(self):
|
| 918 |
+
if getattr(self, '_own_callback', None) is not None:
|
| 919 |
+
return 'calling %r' % (self._own_callback,)
|
| 920 |
+
return super(CTypesFunctionPtr, self)._get_own_repr()
|
| 921 |
+
|
| 922 |
+
def __call__(self, *args):
|
| 923 |
+
if has_varargs:
|
| 924 |
+
assert len(args) >= len(BArgs)
|
| 925 |
+
extraargs = args[len(BArgs):]
|
| 926 |
+
args = args[:len(BArgs)]
|
| 927 |
+
else:
|
| 928 |
+
assert len(args) == len(BArgs)
|
| 929 |
+
ctypes_args = []
|
| 930 |
+
for arg, BArg in zip(args, BArgs):
|
| 931 |
+
ctypes_args.append(BArg._arg_to_ctypes(arg))
|
| 932 |
+
if has_varargs:
|
| 933 |
+
for i, arg in enumerate(extraargs):
|
| 934 |
+
if arg is None:
|
| 935 |
+
ctypes_args.append(ctypes.c_void_p(0)) # NULL
|
| 936 |
+
continue
|
| 937 |
+
if not isinstance(arg, CTypesData):
|
| 938 |
+
raise TypeError(
|
| 939 |
+
"argument %d passed in the variadic part "
|
| 940 |
+
"needs to be a cdata object (got %s)" %
|
| 941 |
+
(1 + len(BArgs) + i, type(arg).__name__))
|
| 942 |
+
ctypes_args.append(arg._arg_to_ctypes(arg))
|
| 943 |
+
result = self._as_ctype_ptr(*ctypes_args)
|
| 944 |
+
return BResult._from_ctypes(result)
|
| 945 |
+
#
|
| 946 |
+
CTypesFunctionPtr._fix_class()
|
| 947 |
+
return CTypesFunctionPtr
|
| 948 |
+
|
| 949 |
+
def new_enum_type(self, name, enumerators, enumvalues, CTypesInt):
|
| 950 |
+
assert isinstance(name, str)
|
| 951 |
+
reverse_mapping = dict(zip(reversed(enumvalues),
|
| 952 |
+
reversed(enumerators)))
|
| 953 |
+
#
|
| 954 |
+
class CTypesEnum(CTypesInt):
|
| 955 |
+
__slots__ = []
|
| 956 |
+
_reftypename = '%s &' % name
|
| 957 |
+
|
| 958 |
+
def _get_own_repr(self):
|
| 959 |
+
value = self._value
|
| 960 |
+
try:
|
| 961 |
+
return '%d: %s' % (value, reverse_mapping[value])
|
| 962 |
+
except KeyError:
|
| 963 |
+
return str(value)
|
| 964 |
+
|
| 965 |
+
def _to_string(self, maxlen):
|
| 966 |
+
value = self._value
|
| 967 |
+
try:
|
| 968 |
+
return reverse_mapping[value]
|
| 969 |
+
except KeyError:
|
| 970 |
+
return str(value)
|
| 971 |
+
#
|
| 972 |
+
CTypesEnum._fix_class()
|
| 973 |
+
return CTypesEnum
|
| 974 |
+
|
| 975 |
+
def get_errno(self):
|
| 976 |
+
return ctypes.get_errno()
|
| 977 |
+
|
| 978 |
+
def set_errno(self, value):
|
| 979 |
+
ctypes.set_errno(value)
|
| 980 |
+
|
| 981 |
+
def string(self, b, maxlen=-1):
|
| 982 |
+
return b._to_string(maxlen)
|
| 983 |
+
|
| 984 |
+
def buffer(self, bptr, size=-1):
|
| 985 |
+
raise NotImplementedError("buffer() with ctypes backend")
|
| 986 |
+
|
| 987 |
+
def sizeof(self, cdata_or_BType):
|
| 988 |
+
if isinstance(cdata_or_BType, CTypesData):
|
| 989 |
+
return cdata_or_BType._get_size_of_instance()
|
| 990 |
+
else:
|
| 991 |
+
assert issubclass(cdata_or_BType, CTypesData)
|
| 992 |
+
return cdata_or_BType._get_size()
|
| 993 |
+
|
| 994 |
+
def alignof(self, BType):
|
| 995 |
+
assert issubclass(BType, CTypesData)
|
| 996 |
+
return BType._alignment()
|
| 997 |
+
|
| 998 |
+
def newp(self, BType, source):
|
| 999 |
+
if not issubclass(BType, CTypesData):
|
| 1000 |
+
raise TypeError
|
| 1001 |
+
return BType._newp(source)
|
| 1002 |
+
|
| 1003 |
+
def cast(self, BType, source):
|
| 1004 |
+
return BType._cast_from(source)
|
| 1005 |
+
|
| 1006 |
+
def callback(self, BType, source, error, onerror):
|
| 1007 |
+
assert onerror is None # XXX not implemented
|
| 1008 |
+
return BType(source, error)
|
| 1009 |
+
|
| 1010 |
+
_weakref_cache_ref = None
|
| 1011 |
+
|
| 1012 |
+
def gcp(self, cdata, destructor, size=0):
|
| 1013 |
+
if self._weakref_cache_ref is None:
|
| 1014 |
+
import weakref
|
| 1015 |
+
class MyRef(weakref.ref):
|
| 1016 |
+
def __eq__(self, other):
|
| 1017 |
+
myref = self()
|
| 1018 |
+
return self is other or (
|
| 1019 |
+
myref is not None and myref is other())
|
| 1020 |
+
def __ne__(self, other):
|
| 1021 |
+
return not (self == other)
|
| 1022 |
+
def __hash__(self):
|
| 1023 |
+
try:
|
| 1024 |
+
return self._hash
|
| 1025 |
+
except AttributeError:
|
| 1026 |
+
self._hash = hash(self())
|
| 1027 |
+
return self._hash
|
| 1028 |
+
self._weakref_cache_ref = {}, MyRef
|
| 1029 |
+
weak_cache, MyRef = self._weakref_cache_ref
|
| 1030 |
+
|
| 1031 |
+
if destructor is None:
|
| 1032 |
+
try:
|
| 1033 |
+
del weak_cache[MyRef(cdata)]
|
| 1034 |
+
except KeyError:
|
| 1035 |
+
raise TypeError("Can remove destructor only on a object "
|
| 1036 |
+
"previously returned by ffi.gc()")
|
| 1037 |
+
return None
|
| 1038 |
+
|
| 1039 |
+
def remove(k):
|
| 1040 |
+
cdata, destructor = weak_cache.pop(k, (None, None))
|
| 1041 |
+
if destructor is not None:
|
| 1042 |
+
destructor(cdata)
|
| 1043 |
+
|
| 1044 |
+
new_cdata = self.cast(self.typeof(cdata), cdata)
|
| 1045 |
+
assert new_cdata is not cdata
|
| 1046 |
+
weak_cache[MyRef(new_cdata, remove)] = (cdata, destructor)
|
| 1047 |
+
return new_cdata
|
| 1048 |
+
|
| 1049 |
+
typeof = type
|
| 1050 |
+
|
| 1051 |
+
def getcname(self, BType, replace_with):
|
| 1052 |
+
return BType._get_c_name(replace_with)
|
| 1053 |
+
|
| 1054 |
+
def typeoffsetof(self, BType, fieldname, num=0):
|
| 1055 |
+
if isinstance(fieldname, str):
|
| 1056 |
+
if num == 0 and issubclass(BType, CTypesGenericPtr):
|
| 1057 |
+
BType = BType._BItem
|
| 1058 |
+
if not issubclass(BType, CTypesBaseStructOrUnion):
|
| 1059 |
+
raise TypeError("expected a struct or union ctype")
|
| 1060 |
+
BField = BType._bfield_types[fieldname]
|
| 1061 |
+
if BField is Ellipsis:
|
| 1062 |
+
raise TypeError("not supported for bitfields")
|
| 1063 |
+
return (BField, BType._offsetof(fieldname))
|
| 1064 |
+
elif isinstance(fieldname, (int, long)):
|
| 1065 |
+
if issubclass(BType, CTypesGenericArray):
|
| 1066 |
+
BType = BType._CTPtr
|
| 1067 |
+
if not issubclass(BType, CTypesGenericPtr):
|
| 1068 |
+
raise TypeError("expected an array or ptr ctype")
|
| 1069 |
+
BItem = BType._BItem
|
| 1070 |
+
offset = BItem._get_size() * fieldname
|
| 1071 |
+
if offset > sys.maxsize:
|
| 1072 |
+
raise OverflowError
|
| 1073 |
+
return (BItem, offset)
|
| 1074 |
+
else:
|
| 1075 |
+
raise TypeError(type(fieldname))
|
| 1076 |
+
|
| 1077 |
+
def rawaddressof(self, BTypePtr, cdata, offset=None):
|
| 1078 |
+
if isinstance(cdata, CTypesBaseStructOrUnion):
|
| 1079 |
+
ptr = ctypes.pointer(type(cdata)._to_ctypes(cdata))
|
| 1080 |
+
elif isinstance(cdata, CTypesGenericPtr):
|
| 1081 |
+
if offset is None or not issubclass(type(cdata)._BItem,
|
| 1082 |
+
CTypesBaseStructOrUnion):
|
| 1083 |
+
raise TypeError("unexpected cdata type")
|
| 1084 |
+
ptr = type(cdata)._to_ctypes(cdata)
|
| 1085 |
+
elif isinstance(cdata, CTypesGenericArray):
|
| 1086 |
+
ptr = type(cdata)._to_ctypes(cdata)
|
| 1087 |
+
else:
|
| 1088 |
+
raise TypeError("expected a <cdata 'struct-or-union'>")
|
| 1089 |
+
if offset:
|
| 1090 |
+
ptr = ctypes.cast(
|
| 1091 |
+
ctypes.c_void_p(
|
| 1092 |
+
ctypes.cast(ptr, ctypes.c_void_p).value + offset),
|
| 1093 |
+
type(ptr))
|
| 1094 |
+
return BTypePtr._from_ctypes(ptr)
|
| 1095 |
+
|
| 1096 |
+
|
| 1097 |
+
class CTypesLibrary(object):
|
| 1098 |
+
|
| 1099 |
+
def __init__(self, backend, cdll):
|
| 1100 |
+
self.backend = backend
|
| 1101 |
+
self.cdll = cdll
|
| 1102 |
+
|
| 1103 |
+
def load_function(self, BType, name):
|
| 1104 |
+
c_func = getattr(self.cdll, name)
|
| 1105 |
+
funcobj = BType._from_ctypes(c_func)
|
| 1106 |
+
funcobj._name = name
|
| 1107 |
+
return funcobj
|
| 1108 |
+
|
| 1109 |
+
def read_variable(self, BType, name):
|
| 1110 |
+
try:
|
| 1111 |
+
ctypes_obj = BType._ctype.in_dll(self.cdll, name)
|
| 1112 |
+
except AttributeError as e:
|
| 1113 |
+
raise NotImplementedError(e)
|
| 1114 |
+
return BType._from_ctypes(ctypes_obj)
|
| 1115 |
+
|
| 1116 |
+
def write_variable(self, BType, name, value):
|
| 1117 |
+
new_ctypes_obj = BType._to_ctypes(value)
|
| 1118 |
+
ctypes_obj = BType._ctype.in_dll(self.cdll, name)
|
| 1119 |
+
ctypes.memmove(ctypes.addressof(ctypes_obj),
|
| 1120 |
+
ctypes.addressof(new_ctypes_obj),
|
| 1121 |
+
ctypes.sizeof(BType._ctype))
|