Skip to content

Commit 2148a59

Browse files
committed
Add LZMAFile wrapper for pickle protocol 5
1 parent 407035e commit 2148a59

File tree

1 file changed

+29
-9
lines changed

1 file changed

+29
-9
lines changed

pandas/compat/__init__.py

+29-9
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,16 @@
1010
from __future__ import annotations
1111

1212
import os
13+
from pickle import PickleBuffer
1314
import platform
1415
import sys
15-
from typing import TYPE_CHECKING
16+
17+
try:
18+
import lzma
19+
20+
has_lzma = True
21+
except ImportError:
22+
has_lzma = False
1623

1724
from pandas._typing import F
1825
from pandas.compat.numpy import (
@@ -31,16 +38,31 @@
3138
pa_version_under9p0,
3239
)
3340

34-
if TYPE_CHECKING:
35-
import lzma
36-
3741
PY39 = sys.version_info >= (3, 9)
3842
PY310 = sys.version_info >= (3, 10)
3943
PY311 = sys.version_info >= (3, 11)
4044
PYPY = platform.python_implementation() == "PyPy"
4145
IS64 = sys.maxsize > 2**32
4246

4347

48+
if has_lzma:
49+
50+
class _LZMAFile(lzma.LZMAFile):
51+
def write(self, b) -> None:
52+
if isinstance(b, PickleBuffer):
53+
# Workaround issue where `lzma.LZMAFile` expects `len`
54+
# to return the number of bytes in `b` by converting
55+
# `b` into something that meets that constraint with
56+
# minimal copying.
57+
try:
58+
# coerce to 1-D `uint8` C-contiguous `memoryview` zero-copy
59+
b = b.raw()
60+
except BufferError:
61+
# perform in-memory copy if buffer is not contiguous
62+
b = bytes(b)
63+
return super().write(b)
64+
65+
4466
def set_function_name(f: F, name: str, cls) -> F:
4567
"""
4668
Bind the name/qualname attributes of the function.
@@ -126,7 +148,7 @@ def is_ci_environment() -> bool:
126148
return os.environ.get("PANDAS_CI", "0") == "1"
127149

128150

129-
def get_lzma_file() -> type[lzma.LZMAFile]:
151+
def get_lzma_file() -> type[_LZMAFile]:
130152
"""
131153
Importing the `LZMAFile` class from the `lzma` module.
132154
@@ -140,15 +162,13 @@ def get_lzma_file() -> type[lzma.LZMAFile]:
140162
RuntimeError
141163
If the `lzma` module was not imported correctly, or didn't exist.
142164
"""
143-
try:
144-
import lzma
145-
except ImportError:
165+
if not has_lzma:
146166
raise RuntimeError(
147167
"lzma module not available. "
148168
"A Python re-install with the proper dependencies, "
149169
"might be required to solve this issue."
150170
)
151-
return lzma.LZMAFile
171+
return _LZMAFile
152172

153173

154174
__all__ = [

0 commit comments

Comments
 (0)