Skip to content

Commit ffc58d3

Browse files
committed
Move all compat compressors into a single file
1 parent 742788f commit ffc58d3

File tree

6 files changed

+83
-95
lines changed

6 files changed

+83
-95
lines changed

pandas/compat/__init__.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
import os
1313
import platform
1414
import sys
15-
from typing import TYPE_CHECKING
1615

1716
from pandas._typing import F
17+
import pandas.compat._compressors
1818
from pandas.compat.numpy import (
1919
is_numpy_dev,
2020
np_version_under1p21,
@@ -26,9 +26,6 @@
2626
pa_version_under9p0,
2727
)
2828

29-
if TYPE_CHECKING:
30-
import pandas.compat.lzma
31-
3229
PY39 = sys.version_info >= (3, 9)
3330
PY310 = sys.version_info >= (3, 10)
3431
PY311 = sys.version_info >= (3, 11)
@@ -121,7 +118,7 @@ def is_ci_environment() -> bool:
121118
return os.environ.get("PANDAS_CI", "0") == "1"
122119

123120

124-
def get_lzma_file() -> type[pandas.compat.lzma.LZMAFile]:
121+
def get_lzma_file() -> type[pandas.compat._compressors.LZMAFile]:
125122
"""
126123
Importing the `LZMAFile` class from the `lzma` module.
127124
@@ -135,15 +132,13 @@ def get_lzma_file() -> type[pandas.compat.lzma.LZMAFile]:
135132
RuntimeError
136133
If the `lzma` module was not imported correctly, or didn't exist.
137134
"""
138-
try:
139-
import pandas.compat.lzma
140-
except ImportError:
135+
if not pandas.compat._compressors.has_lzma:
141136
raise RuntimeError(
142137
"lzma module not available. "
143138
"A Python re-install with the proper dependencies, "
144139
"might be required to solve this issue."
145140
)
146-
return pandas.compat.lzma.LZMAFile
141+
return pandas.compat._compressors.LZMAFile
147142

148143

149144
__all__ = [

pandas/compat/_compressors.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
"""
2+
Patched ``BZ2File`` and ``LZMAFile`` to handle pickle protocol 5.
3+
"""
4+
5+
from __future__ import annotations
6+
7+
import bz2
8+
import pickle
9+
import sys
10+
11+
try:
12+
import lzma
13+
14+
has_lzma = True
15+
except ImportError:
16+
has_lzma = False
17+
18+
19+
PY310 = sys.version_info >= (3, 10)
20+
21+
22+
def flatten_buffer(
23+
b: bytes | bytearray | memoryview | pickle.PickleBuffer,
24+
) -> bytes | memoryview:
25+
"""
26+
Return some 1-D `uint8` typed buffer.
27+
28+
Coerces anything that does not match that description to one that does
29+
without copying if possible (otherwise will copy).
30+
"""
31+
32+
if isinstance(b, (bytes, bytearray)):
33+
return b
34+
35+
if not isinstance(b, pickle.PickleBuffer):
36+
b = pickle.PickleBuffer(b)
37+
38+
try:
39+
# coerce to 1-D `uint8` C-contiguous `memoryview` zero-copy
40+
return b.raw()
41+
except BufferError:
42+
# perform in-memory copy if buffer is not contiguous
43+
return memoryview(b).tobytes("A")
44+
45+
46+
if not PY310:
47+
48+
class BZ2File(bz2.BZ2File):
49+
def write(self, b) -> int:
50+
# Workaround issue where `bz2.BZ2File` expects `len`
51+
# to return the number of bytes in `b` by converting
52+
# `b` into something that meets that constraint with
53+
# minimal copying.
54+
#
55+
# Note: This is fixed in Python 3.10.
56+
return super().write(flatten_buffer(b))
57+
58+
if has_lzma:
59+
60+
class LZMAFile(lzma.LZMAFile):
61+
def write(self, b) -> int:
62+
# Workaround issue where `lzma.LZMAFile` expects `len`
63+
# to return the number of bytes in `b` by converting
64+
# `b` into something that meets that constraint with
65+
# minimal copying.
66+
#
67+
# Note: This is fixed in Python 3.10.
68+
return super().write(flatten_buffer(b))
69+
70+
else:
71+
72+
class BZ2File(bz2.BZ2File):
73+
pass
74+
75+
if has_lzma:
76+
77+
class LZMAFile(lzma.LZMAFile):
78+
pass

pandas/compat/_utils.py

Lines changed: 0 additions & 31 deletions
This file was deleted.

pandas/compat/bz2.py

Lines changed: 0 additions & 27 deletions
This file was deleted.

pandas/compat/lzma.py

Lines changed: 0 additions & 27 deletions
This file was deleted.

pandas/tests/io/test_pickle.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@
3838
get_lzma_file,
3939
is_platform_little_endian,
4040
)
41+
from pandas.compat._compressors import flatten_buffer
4142
from pandas.compat._optional import import_optional_dependency
42-
from pandas.compat._utils import flatten_buffer
4343
import pandas.util._test_decorators as td
4444

4545
import pandas as pd

0 commit comments

Comments
 (0)