Skip to content

Commit 26aa525

Browse files
authored
Merge branch 'master' into build_wheel
2 parents cd98c41 + 42702d8 commit 26aa525

File tree

4 files changed

+117
-0
lines changed

4 files changed

+117
-0
lines changed

docs/release.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ Release notes
44
Upcoming Release
55
----------------
66

7+
* Add Base64 codec.
8+
By :user: `Trevor Manz <manzt>`, :issue: `176`.
9+
710
* Add partial decompression of Blosc compressed arrays.
811
By :user:`Andrew Fulton <andrewfulton9>`, :issue:`235`.
912

numcodecs/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@
8989
from numcodecs.pickles import Pickle
9090
register_codec(Pickle)
9191

92+
from numcodecs.base64 import Base64
93+
register_codec(Base64)
94+
9295
try:
9396
from numcodecs.msgpacks import MsgPack
9497
register_codec(MsgPack)

numcodecs/base64.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import base64 as _base64
2+
3+
from .abc import Codec
4+
from .compat import ensure_contiguous_ndarray, ndarray_copy
5+
6+
7+
class Base64(Codec):
8+
"""Codec providing base64 compression via the Python standard library."""
9+
10+
codec_id = "base64"
11+
12+
def encode(self, buf):
13+
# normalise inputs
14+
buf = ensure_contiguous_ndarray(buf)
15+
# do compression
16+
compressed = _base64.standard_b64encode(buf)
17+
return compressed
18+
19+
def decode(self, buf, out=None):
20+
# normalise inputs
21+
buf = ensure_contiguous_ndarray(buf)
22+
if out is not None:
23+
out = ensure_contiguous_ndarray(out)
24+
# do decompression
25+
decompressed = _base64.standard_b64decode(buf)
26+
# handle destination
27+
return ndarray_copy(decompressed, out)

numcodecs/tests/test_base64.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import itertools
2+
3+
4+
import numpy as np
5+
import pytest
6+
7+
8+
from numcodecs.base64 import Base64
9+
from numcodecs.tests.common import (
10+
check_encode_decode,
11+
check_repr,
12+
check_backwards_compatibility,
13+
check_err_decode_object_buffer,
14+
check_err_encode_object_buffer,
15+
)
16+
17+
18+
codecs = [
19+
Base64(),
20+
]
21+
22+
23+
# mix of dtypes: integer, float, bool, string
24+
# mix of shapes: 1D, 2D, 3D
25+
# mix of orders: C, F
26+
arrays = [
27+
np.arange(1000, dtype="i4"),
28+
np.linspace(1000, 1001, 1000, dtype="f8"),
29+
np.random.normal(loc=1000, scale=1, size=(100, 10)),
30+
np.random.randint(0, 2, size=1000, dtype=bool).reshape(100, 10, order="F"),
31+
np.random.choice([b"a", b"bb", b"ccc"], size=1000).reshape(10, 10, 10),
32+
np.random.randint(0, 2 ** 60, size=1000, dtype="u8").view("M8[ns]"),
33+
np.random.randint(0, 2 ** 60, size=1000, dtype="u8").view("m8[ns]"),
34+
np.random.randint(0, 2 ** 25, size=1000, dtype="u8").view("M8[m]"),
35+
np.random.randint(0, 2 ** 25, size=1000, dtype="u8").view("m8[m]"),
36+
np.random.randint(-(2 ** 63), -(2 ** 63) + 20, size=1000, dtype="i8").view("M8[ns]"),
37+
np.random.randint(-(2 ** 63), -(2 ** 63) + 20, size=1000, dtype="i8").view("m8[ns]"),
38+
np.random.randint(-(2 ** 63), -(2 ** 63) + 20, size=1000, dtype="i8").view("M8[m]"),
39+
np.random.randint(-(2 ** 63), -(2 ** 63) + 20, size=1000, dtype="i8").view("m8[m]"),
40+
]
41+
42+
43+
def test_encode_decode():
44+
for arr, codec in itertools.product(arrays, codecs):
45+
check_encode_decode(arr, codec)
46+
47+
48+
def test_repr():
49+
check_repr("Base64()")
50+
51+
52+
def test_eq():
53+
assert Base64() == Base64()
54+
assert not Base64() != Base64()
55+
assert Base64() != "foo"
56+
assert "foo" != Base64()
57+
assert not Base64() == "foo"
58+
59+
60+
def test_backwards_compatibility():
61+
check_backwards_compatibility(Base64.codec_id, arrays, codecs)
62+
63+
64+
def test_err_decode_object_buffer():
65+
check_err_decode_object_buffer(Base64())
66+
67+
68+
def test_err_encode_object_buffer():
69+
check_err_encode_object_buffer(Base64())
70+
71+
72+
def test_err_encode_list():
73+
data = ["foo", "bar", "baz"]
74+
for codec in codecs:
75+
with pytest.raises(TypeError):
76+
codec.encode(data)
77+
78+
79+
def test_err_encode_non_contiguous():
80+
# non-contiguous memory
81+
arr = np.arange(1000, dtype="i4")[::2]
82+
for codec in codecs:
83+
with pytest.raises(ValueError):
84+
codec.encode(arr)

0 commit comments

Comments
 (0)