Commit 83029192 authored by Tres Seaver's avatar Tres Seaver

Document / enforce that fsBTree deals in bytes, not text.

parent ab9cfb5c
......@@ -1420,10 +1420,10 @@ def to_long(self, v):
return int(v)
def to_str(l):
def to_bytes(l):
def to(self, v):
if not (isinstance(v, str) and len(v) == l):
raise TypeError("%s-character string expected" % l)
if not (isinstance(v, bytes) and len(v) == l):
raise TypeError("%s-byte array expected" % l)
return v
return to
......
......@@ -26,6 +26,8 @@ if sys.version_info[0] < 3: #pragma NO COVER Python2
cmp = cmp
_bytes = str
def _ascii(x):
return bytes(x)
def _u(s, encoding='unicode_escape'):
return unicode(s, encoding)
......@@ -45,6 +47,8 @@ else: #pragma NO COVER Python3
return (x > y) - (y > x)
_bytes = bytes
def _ascii(x):
return bytes(x, 'ascii')
def _u(s, encoding=None):
if encoding is None:
......
......@@ -71,15 +71,19 @@ typedef unsigned char char6[6];
#include "Python.h"
static PyObject *bucket_toString(PyObject *self);
static PyObject *bucket_toBytes(PyObject *self);
static PyObject *bucket_fromString(PyObject *self, PyObject *state);
static PyObject *bucket_fromBytes(PyObject *self, PyObject *state);
#define EXTRA_BUCKET_METHODS \
{"toString", (PyCFunction) bucket_toString, METH_NOARGS, \
"toString() -- Return the state as a string"}, \
{"fromString", (PyCFunction) bucket_fromString, METH_O, \
"fromString(s) -- Set the state of the object from a string"}, \
{"toBytes", (PyCFunction) bucket_toBytes, METH_NOARGS, \
"toBytes() -- Return the state as a bytes array"}, \
{"fromBytes", (PyCFunction) bucket_fromBytes, METH_O, \
"fromSBytes(s) -- Set the state of the object from a bytes array"}, \
{"toString", (PyCFunction) bucket_toBytes, METH_NOARGS, \
"toString() -- Deprecated alias for 'toBytes'"}, \
{"fromString", (PyCFunction) bucket_fromBytes, METH_O, \
"fromString(s) -- Deprecated alias for 'fromBytes'"}, \
#ifdef PY3K
#define INITMODULE PyInit__fsBTree
......@@ -89,7 +93,7 @@ static PyObject *bucket_fromString(PyObject *self, PyObject *state);
#include "BTreeModuleTemplate.c"
static PyObject *
bucket_toString(PyObject *oself)
bucket_toBytes(PyObject *oself)
{
Bucket *self = (Bucket *)oself;
PyObject *items = NULL;
......@@ -115,7 +119,7 @@ bucket_toString(PyObject *oself)
}
static PyObject *
bucket_fromString(PyObject *oself, PyObject *state)
bucket_fromBytes(PyObject *oself, PyObject *state)
{
Bucket *self = (Bucket *)oself;
int len;
......
......@@ -14,6 +14,7 @@
# fsBTrees are data structures used for ZODB FileStorage. They are not
# expected to be "public" excpect to FileStorage.
# Each item in an fsBTree maps a two-byte key to a six-byte value.
__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
'fsBucket', 'fsSet', 'fsBTree', 'fsTreeSet',
......@@ -31,14 +32,14 @@ from ._base import TreeSet
from ._base import difference as _difference
from ._base import intersection as _intersection
from ._base import set_operation as _set_operation
from ._base import to_str as _to_str
from ._base import to_bytes as _to_bytes
from ._base import union as _union
_BUCKET_SIZE = 500
_TREE_SIZE = 500
using64bits = False
_to_key = _to_str(2)
_to_value = _to_str(6)
_to_key = _to_bytes(2)
_to_value = _to_bytes(6)
class fsBucketPy(Bucket):
......@@ -47,7 +48,7 @@ class fsBucketPy(Bucket):
_to_value = _to_value
def toString(self):
return ''.join(self._keys) + ''.join(self._values)
return b''.join(self._keys) + b''.join(self._values)
def fromString(self, v):
length = len(v)
......
......@@ -2909,18 +2909,18 @@ class Test_helpers(unittest.TestCase):
faux_self = object()
self.assertRaises(TypeError, to_long, faux_self, ())
def test_to_str_w_ok(self):
from BTrees._base import to_str
def test_to_bytes_w_ok(self):
from BTrees._base import to_bytes
faux_self = object()
conv = to_str(3)
self.assertEqual(conv(faux_self, 'abc'), 'abc')
conv = to_bytes(3)
self.assertEqual(conv(faux_self, b'abc'), b'abc')
def test_to_str_w_invalid_length(self):
from BTrees._base import to_str
def test_to_bytes_w_invalid_length(self):
from BTrees._base import to_bytes
faux_self = object()
conv = to_str(3)
self.assertRaises(TypeError, conv, faux_self, 'ab')
self.assertRaises(TypeError, conv, faux_self, 'abcd')
conv = to_bytes(3)
self.assertRaises(TypeError, conv, faux_self, b'ab')
self.assertRaises(TypeError, conv, faux_self, b'abcd')
def test_MERGE(self):
from BTrees._base import MERGE
......
......@@ -19,24 +19,28 @@ class fsBucketBase(object):
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def _makeBytesItems(self):
from .._compat import _ascii
return[(_ascii(c*2), _ascii(c*6)) for c in 'abcdef']
def test_toString(self):
bucket = self._makeOne([(c*2, c*6) for c in 'abcdef'])
bucket = self._makeOne(self._makeBytesItems())
self.assertEqual(bucket.toString(),
'aabbccddeeffaaaaaabbbbbbccccccddddddeeeeeeffffff')
b'aabbccddeeffaaaaaabbbbbbccccccddddddeeeeeeffffff')
def test_fromString(self):
before = self._makeOne([(c*2, c*6) for c in 'abcdef'])
before = self._makeOne(self._makeBytesItems())
after = before.fromString(before.toString())
self.assertEqual(before.__getstate__(), after.__getstate__())
def test_fromString_empty(self):
before = self._makeOne([(c*2, c*6) for c in 'abcdef'])
after = before.fromString('')
before = self._makeOne(self._makeBytesItems())
after = before.fromString(b'')
self.assertEqual(after.__getstate__(), ((),))
def test_fromString_invalid(self):
bucket = self._makeOne([(c*2, c*6) for c in 'abcdef'])
self.assertRaises(ValueError, bucket.fromString, 'xxx')
def test_fromString_invalid_length(self):
bucket = self._makeOne(self._makeBytesItems())
self.assertRaises(ValueError, bucket.fromString, b'xxx')
class fsBucketTests(unittest.TestCase, fsBucketBase):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment