Skip pyzstd with Python 3.14+

3.14 has builtin zstd support, so use the builtin one there.
This commit is contained in:
Christoph Reiter
2025-11-08 17:08:11 +01:00
parent 6fd17c6382
commit 3cc94c10a2
5 changed files with 47 additions and 30 deletions

View File

@@ -1,34 +1,48 @@
import tarfile
from pyzstd import ZstdFile, ZstdError
HAS_ZSTD = True
try:
from compression import zstd
except ImportError:
HAS_ZSTD = False
class ExtTarFile(tarfile.TarFile):
"""Extends TarFile to support zstandard"""
ExtTarFile: type[tarfile.TarFile]
@classmethod
def zstdopen(cls, name, mode="r", fileobj=None, **kwargs): # type: ignore
"""Open zstd compressed tar archive"""
if not HAS_ZSTD:
from pyzstd import ZstdFile, ZstdError
if mode not in ("r", "w", "x", "a"):
raise ValueError("mode must be 'r', 'w' or 'x' or 'a'")
class ZstTarFile(tarfile.TarFile):
"""Extends TarFile to support zstandard"""
zstfileobj = None
try:
zstfileobj = ZstdFile(fileobj or name, mode)
if "r" in mode:
zstfileobj.peek(1) # raises ZstdError if not a zstd file
except (ZstdError, EOFError) as e:
if zstfileobj is not None:
@classmethod
def zstdopen(cls, name, mode="r", fileobj=None, **kwargs): # type: ignore
"""Open zstd compressed tar archive"""
if mode not in ("r", "w", "x", "a"):
raise ValueError("mode must be 'r', 'w' or 'x' or 'a'")
zstfileobj = None
try:
zstfileobj = ZstdFile(fileobj or name, mode)
if "r" in mode:
zstfileobj.peek(1) # raises ZstdError if not a zstd file
except (ZstdError, EOFError) as e:
if zstfileobj is not None:
zstfileobj.close()
raise tarfile.ReadError("not a zstd file") from e
try:
t = cls.taropen(name, mode, zstfileobj, **kwargs)
except Exception:
zstfileobj.close()
raise tarfile.ReadError("not a zstd file") from e
raise
try:
t = cls.taropen(name, mode, zstfileobj, **kwargs)
except Exception:
zstfileobj.close()
raise
t._extfileobj = False
return t
t._extfileobj = False
return t
OPEN_METH = {"zst": "zstdopen", **tarfile.TarFile.OPEN_METH}
OPEN_METH = {"zstd": "zstdopen", **tarfile.TarFile.OPEN_METH}
ExtTarFile = ZstTarFile
else:
assert zstd
ExtTarFile = tarfile.TarFile

View File

@@ -3,7 +3,10 @@
import asyncio
import pyzstd
try:
from compression import zstd
except ImportError:
import pyzstd as zstd
from ..appconfig import CYGWIN_METADATA_URL, REQUEST_TIMEOUT
from ..appstate import ExtId, ExtInfo, state
@@ -63,7 +66,7 @@ async def update_cygwin_versions() -> None:
logger.info("update cygwin info")
logger.info(f"Loading {url!r}")
data = await get_content_cached(url, timeout=REQUEST_TIMEOUT)
data = pyzstd.decompress(data)
data = zstd.decompress(data)
cygwin_versions, cygwin_versions_mingw64 = await asyncio.to_thread(parse_cygwin_versions, url, data)
state.set_ext_infos(ExtId("cygwin", "Cygwin", True, True), cygwin_versions)
state.set_ext_infos(ExtId("cygwin-mingw64", "Cygwin-mingw64", False, True), cygwin_versions_mingw64)

View File

@@ -17,7 +17,7 @@ dependencies = [
"MarkupSafe>=3.0.2,<4",
"uvicorn-worker>=0.4.0,<0.5",
"packageurl-python>=0.17.0,<0.18",
"pyzstd>=0.18.0,<0.19",
"pyzstd>=0.18.0,<0.19; python_version < '3.14'",
"mcp>=1.10.1,<2",
]

View File

@@ -25,7 +25,7 @@ def test_zst() -> None:
def test_zstd_write() -> None:
fileobj = io.BytesIO()
with ExtTarFile.open(fileobj=fileobj, mode='w:zstd') as tar: # type: ignore
with ExtTarFile.open(fileobj=fileobj, mode='w:zst') as tar: # type: ignore
data = b"Hello world!"
info = tarfile.TarInfo("test.txt")
info.size = len(data)

4
uv.lock generated
View File

@@ -485,7 +485,7 @@ dependencies = [
{ name = "mcp" },
{ name = "packageurl-python" },
{ name = "pydantic" },
{ name = "pyzstd" },
{ name = "pyzstd", marker = "python_full_version < '3.14'" },
{ name = "uvicorn" },
{ name = "uvicorn-worker" },
]
@@ -512,7 +512,7 @@ requires-dist = [
{ name = "mcp", specifier = ">=1.10.1,<2" },
{ name = "packageurl-python", specifier = ">=0.17.0,<0.18" },
{ name = "pydantic", specifier = ">=2.0.3,<3" },
{ name = "pyzstd", specifier = ">=0.18.0,<0.19" },
{ name = "pyzstd", marker = "python_full_version < '3.14'", specifier = ">=0.18.0,<0.19" },
{ name = "uvicorn", specifier = ">=0.38.0,<0.39" },
{ name = "uvicorn-worker", specifier = ">=0.4.0,<0.5" },
]