summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin v. Löwis <martin@v.loewis.de>2007-07-18 02:28:27 (GMT)
committerMartin v. Löwis <martin@v.loewis.de>2007-07-18 02:28:27 (GMT)
commit10a60b3ec0cdf7eeac98258fc53a33b7026f8ff3 (patch)
tree533e2a67c2c082cd9534c70293977f9245425188
parent6f2df4d5e193d54244b0c2de91ef0ab1604b9243 (diff)
downloadcpython-10a60b3ec0cdf7eeac98258fc53a33b7026f8ff3.zip
cpython-10a60b3ec0cdf7eeac98258fc53a33b7026f8ff3.tar.gz
cpython-10a60b3ec0cdf7eeac98258fc53a33b7026f8ff3.tar.bz2
Change Py_BuildValue to generate Unicode objects for
's' and 'c' codes. Change pickle to dump bytes objects using the 'S' code, and to load the 'S' code as byte objects. Change datetime and array to generate and expect bytes objects in reduce/unreduce.
-rw-r--r--Lib/pickle.py20
-rw-r--r--Lib/test/test_datetime.py3
-rw-r--r--Modules/arraymodule.c2
-rw-r--r--Modules/cPickle.c109
-rw-r--r--Modules/datetimemodule.c50
-rw-r--r--Objects/bytesobject.c3
-rw-r--r--Objects/exceptions.c20
-rw-r--r--Python/modsupport.c4
8 files changed, 166 insertions, 45 deletions
diff --git a/Lib/pickle.py b/Lib/pickle.py
index 27f7eca..c158b8d 100644
--- a/Lib/pickle.py
+++ b/Lib/pickle.py
@@ -506,6 +506,20 @@ class Pickler:
self.memoize(obj)
dispatch[str8] = save_string
+ def save_bytes(self, obj):
+ # Like save_string
+ if self.bin:
+ n = len(obj)
+ if n < 256:
+ self.write(SHORT_BINSTRING + bytes([n]) + bytes(obj))
+ else:
+ self.write(BINSTRING + pack("<i", n) + bytes(obj))
+ else:
+ # Strip leading 'b'
+ self.write(STRING + bytes(repr(obj).lstrip("b")) + b'\n')
+ self.memoize(obj)
+ dispatch[bytes] = save_bytes
+
def save_unicode(self, obj, pack=struct.pack):
if self.bin:
encoded = obj.encode('utf-8')
@@ -931,12 +945,12 @@ class Unpickler:
break
else:
raise ValueError, "insecure string pickle"
- self.append(str8(codecs.escape_decode(rep)[0]))
+ self.append(bytes(codecs.escape_decode(rep)[0]))
dispatch[STRING[0]] = load_string
def load_binstring(self):
len = mloads(b'i' + self.read(4))
- self.append(str8(self.read(len)))
+ self.append(self.read(len))
dispatch[BINSTRING[0]] = load_binstring
def load_unicode(self):
@@ -950,7 +964,7 @@ class Unpickler:
def load_short_binstring(self):
len = ord(self.read(1))
- self.append(str8(self.read(len)))
+ self.append(self.read(len))
dispatch[SHORT_BINSTRING[0]] = load_short_binstring
def load_tuple(self):
diff --git a/Lib/test/test_datetime.py b/Lib/test/test_datetime.py
index ac6d130..cf7051b 100644
--- a/Lib/test/test_datetime.py
+++ b/Lib/test/test_datetime.py
@@ -1097,8 +1097,7 @@ class TestDate(HarmlessMixedComparison, unittest.TestCase):
# This shouldn't blow up because of the month byte alone. If
# the implementation changes to do more-careful checking, it may
# blow up because other fields are insane.
- # XXX Maybe this will have to become bytes?
- self.theclass(str8(base[:2] + chr(ord_byte) + base[3:]))
+ self.theclass(bytes(base[:2] + chr(ord_byte) + base[3:]))
#############################################################################
# datetime tests
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index 11819e2..7ddc7e8 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -1126,7 +1126,7 @@ array_reduce(arrayobject *array)
Py_INCREF(dict);
}
if (array->ob_size > 0) {
- result = Py_BuildValue("O(cs#)O",
+ result = Py_BuildValue("O(cy#)O",
array->ob_type,
array->ob_descr->typecode,
array->ob_item,
diff --git a/Modules/cPickle.c b/Modules/cPickle.c
index d50c743..ff29b67 100644
--- a/Modules/cPickle.c
+++ b/Modules/cPickle.c
@@ -1151,6 +1151,92 @@ save_string(Picklerobject *self, PyObject *args, int doput)
}
+static int
+save_bytes(Picklerobject *self, PyObject *args, int doput)
+{
+ int size, len;
+ PyObject *repr=0;
+
+ if ((size = PyBytes_Size(args)) < 0)
+ return -1;
+
+ if (!self->bin) {
+ char *repr_str;
+
+ static char string = STRING;
+
+ if (!( repr = PyObject_ReprStr8(args)))
+ return -1;
+
+ if ((len = PyString_Size(repr)) < 0)
+ goto err;
+ repr_str = PyString_AS_STRING((PyStringObject *)repr);
+
+ /* Strip leading 's' due to repr() of str8() returning s'...' */
+ if (repr_str[0] == 'b') {
+ repr_str++;
+ len--;
+ }
+
+ if (self->write_func(self, &string, 1) < 0)
+ goto err;
+
+ if (self->write_func(self, repr_str, len) < 0)
+ goto err;
+
+ if (self->write_func(self, "\n", 1) < 0)
+ goto err;
+
+ Py_XDECREF(repr);
+ }
+ else {
+ int i;
+ char c_str[5];
+
+ if ((size = PyBytes_Size(args)) < 0)
+ return -1;
+
+ if (size < 256) {
+ c_str[0] = SHORT_BINSTRING;
+ c_str[1] = size;
+ len = 2;
+ }
+ else if (size <= INT_MAX) {
+ c_str[0] = BINSTRING;
+ for (i = 1; i < 5; i++)
+ c_str[i] = (int)(size >> ((i - 1) * 8));
+ len = 5;
+ }
+ else
+ return -1; /* string too large */
+
+ if (self->write_func(self, c_str, len) < 0)
+ return -1;
+
+ if (size > 128 && Pdata_Check(self->file)) {
+ if (write_other(self, NULL, 0) < 0) return -1;
+ PDATA_APPEND(self->file, args, -1);
+ }
+ else {
+ if (self->write_func(self,
+ PyBytes_AsString(args),
+ size) < 0)
+ return -1;
+ }
+ }
+
+ if (doput)
+ if (put(self, args) < 0)
+ return -1;
+
+ return 0;
+
+ err:
+ Py_XDECREF(repr);
+ return -1;
+}
+
+
/* A copy of PyUnicode_EncodeRawUnicodeEscape() that also translates
backslash and newline characters to \uXXXX escapes. */
static PyObject *
@@ -2086,11 +2172,11 @@ save(Picklerobject *self, PyObject *args, int pers_save)
type = args->ob_type;
switch (type->tp_name[0]) {
- case 'b':
+ case 'b': /* XXX may want to save short byte strings here. */
if (args == Py_False || args == Py_True) {
res = save_bool(self, args);
goto finally;
- }
+ }
break;
case 'i':
if (type == &PyLong_Type) {
@@ -2197,6 +2283,11 @@ save(Picklerobject *self, PyObject *args, int pers_save)
res = save_global(self, args, NULL);
goto finally;
}
+ else if (type == &PyBytes_Type) {
+ res = save_bytes(self, args, 1);
+ goto finally;
+ }
+ break;
}
if (!pers_save && self->inst_pers_func) {
@@ -3131,11 +3222,17 @@ load_string(Unpicklerobject *self)
goto insecure;
/********************************************/
+ /* XXX avoid going through str8 here. */
str = PyString_DecodeEscape(p, len, NULL, 0, NULL);
free(s);
if (str) {
- PDATA_PUSH(self->stack, str, -1);
- res = 0;
+ PyObject *str2 = PyBytes_FromStringAndSize(
+ PyString_AsString(str), PyString_Size(str));
+ Py_DECREF(str);
+ if (str2) {
+ PDATA_PUSH(self->stack, str2, -1);
+ res = 0;
+ }
}
return res;
@@ -3160,7 +3257,7 @@ load_binstring(Unpicklerobject *self)
if (self->read_func(self, &s, l) < 0)
return -1;
- if (!( py_string = PyString_FromStringAndSize(s, l)))
+ if (!( py_string = PyBytes_FromStringAndSize(s, l)))
return -1;
PDATA_PUSH(self->stack, py_string, -1);
@@ -3182,7 +3279,7 @@ load_short_binstring(Unpicklerobject *self)
if (self->read_func(self, &s, l) < 0) return -1;
- if (!( py_string = PyString_FromStringAndSize(s, l))) return -1;
+ if (!( py_string = PyBytes_FromStringAndSize(s, l))) return -1;
PDATA_PUSH(self->stack, py_string, -1);
return 0;
diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c
index 61f9ab7..aa037c2 100644
--- a/Modules/datetimemodule.c
+++ b/Modules/datetimemodule.c
@@ -2183,15 +2183,15 @@ date_new(PyTypeObject *type, PyObject *args, PyObject *kw)
/* Check for invocation from pickle with __getstate__ state */
if (PyTuple_GET_SIZE(args) == 1 &&
- PyString_Check(state = PyTuple_GET_ITEM(args, 0)) &&
- PyString_GET_SIZE(state) == _PyDateTime_DATE_DATASIZE &&
- MONTH_IS_SANE(PyString_AS_STRING(state)[2]))
+ PyBytes_Check(state = PyTuple_GET_ITEM(args, 0)) &&
+ PyBytes_GET_SIZE(state) == _PyDateTime_DATE_DATASIZE &&
+ MONTH_IS_SANE(PyBytes_AS_STRING(state)[2]))
{
PyDateTime_Date *me;
me = (PyDateTime_Date *) (type->tp_alloc(type, 0));
if (me != NULL) {
- char *pdata = PyString_AS_STRING(state);
+ char *pdata = PyBytes_AS_STRING(state);
memcpy(me->data, pdata, _PyDateTime_DATE_DATASIZE);
me->hashcode = -1;
}
@@ -2509,13 +2509,13 @@ date_replace(PyDateTime_Date *self, PyObject *args, PyObject *kw)
return clone;
}
-static PyObject *date_getstate(PyDateTime_Date *self);
+static PyObject *date_getstate(PyDateTime_Date *self, int hashable);
static long
date_hash(PyDateTime_Date *self)
{
if (self->hashcode == -1) {
- PyObject *temp = date_getstate(self);
+ PyObject *temp = date_getstate(self, 1);
if (temp != NULL) {
self->hashcode = PyObject_Hash(temp);
Py_DECREF(temp);
@@ -2543,18 +2543,22 @@ date_weekday(PyDateTime_Date *self)
/* __getstate__ isn't exposed */
static PyObject *
-date_getstate(PyDateTime_Date *self)
+date_getstate(PyDateTime_Date *self, int hashable)
{
- return Py_BuildValue(
- "(N)",
- PyString_FromStringAndSize((char *)self->data,
- _PyDateTime_DATE_DATASIZE));
+ PyObject* field;
+ if (hashable)
+ field = PyString_FromStringAndSize(
+ (char*)self->data, _PyDateTime_DATE_DATASIZE);
+ else
+ field = PyBytes_FromStringAndSize(
+ (char*)self->data, _PyDateTime_DATE_DATASIZE);
+ return Py_BuildValue("(N)", field);
}
static PyObject *
date_reduce(PyDateTime_Date *self, PyObject *arg)
{
- return Py_BuildValue("(ON)", self->ob_type, date_getstate(self));
+ return Py_BuildValue("(ON)", self->ob_type, date_getstate(self, 0));
}
static PyMethodDef date_methods[] = {
@@ -2998,9 +3002,9 @@ time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
/* Check for invocation from pickle with __getstate__ state */
if (PyTuple_GET_SIZE(args) >= 1 &&
PyTuple_GET_SIZE(args) <= 2 &&
- PyString_Check(state = PyTuple_GET_ITEM(args, 0)) &&
- PyString_GET_SIZE(state) == _PyDateTime_TIME_DATASIZE &&
- ((unsigned char) (PyString_AS_STRING(state)[0])) < 24)
+ PyBytes_Check(state = PyTuple_GET_ITEM(args, 0)) &&
+ PyBytes_GET_SIZE(state) == _PyDateTime_TIME_DATASIZE &&
+ ((unsigned char) (PyBytes_AS_STRING(state)[0])) < 24)
{
PyDateTime_Time *me;
char aware;
@@ -3016,7 +3020,7 @@ time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
aware = (char)(tzinfo != Py_None);
me = (PyDateTime_Time *) (type->tp_alloc(type, aware));
if (me != NULL) {
- char *pdata = PyString_AS_STRING(state);
+ char *pdata = PyBytes_AS_STRING(state);
memcpy(me->data, pdata, _PyDateTime_TIME_DATASIZE);
me->hashcode = -1;
@@ -3331,7 +3335,7 @@ time_getstate(PyDateTime_Time *self)
PyObject *basestate;
PyObject *result = NULL;
- basestate = PyString_FromStringAndSize((char *)self->data,
+ basestate = PyBytes_FromStringAndSize((char *)self->data,
_PyDateTime_TIME_DATASIZE);
if (basestate != NULL) {
if (! HASTZINFO(self) || self->tzinfo == Py_None)
@@ -3513,9 +3517,9 @@ datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
/* Check for invocation from pickle with __getstate__ state */
if (PyTuple_GET_SIZE(args) >= 1 &&
PyTuple_GET_SIZE(args) <= 2 &&
- PyString_Check(state = PyTuple_GET_ITEM(args, 0)) &&
- PyString_GET_SIZE(state) == _PyDateTime_DATETIME_DATASIZE &&
- MONTH_IS_SANE(PyString_AS_STRING(state)[2]))
+ PyBytes_Check(state = PyTuple_GET_ITEM(args, 0)) &&
+ PyBytes_GET_SIZE(state) == _PyDateTime_DATETIME_DATASIZE &&
+ MONTH_IS_SANE(PyBytes_AS_STRING(state)[2]))
{
PyDateTime_DateTime *me;
char aware;
@@ -3531,7 +3535,7 @@ datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
aware = (char)(tzinfo != Py_None);
me = (PyDateTime_DateTime *) (type->tp_alloc(type , aware));
if (me != NULL) {
- char *pdata = PyString_AS_STRING(state);
+ char *pdata = PyBytes_AS_STRING(state);
memcpy(me->data, pdata, _PyDateTime_DATETIME_DATASIZE);
me->hashcode = -1;
@@ -4375,8 +4379,8 @@ datetime_getstate(PyDateTime_DateTime *self)
PyObject *basestate;
PyObject *result = NULL;
- basestate = PyString_FromStringAndSize((char *)self->data,
- _PyDateTime_DATETIME_DATASIZE);
+ basestate = PyBytes_FromStringAndSize((char *)self->data,
+ _PyDateTime_DATETIME_DATASIZE);
if (basestate != NULL) {
if (! HASTZINFO(self) || self->tzinfo == Py_None)
result = PyTuple_Pack(1, basestate);
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index 532e637..6340b46 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -2724,6 +2724,9 @@ PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
static PyObject *
bytes_reduce(PyBytesObject *self)
{
+ /* XXX: This currently returns a Py_UNICODE-widened string
+ in the tuple which is completely useless. Pickle stopped
+ using it for that reason. */
return Py_BuildValue("(O(s#))",
self->ob_type,
self->ob_bytes == NULL ? "" : self->ob_bytes,
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index 1df0ea0..a401806 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -831,28 +831,32 @@ my_basename(char *name)
static PyObject *
SyntaxError_str(PySyntaxErrorObject *self)
{
- int have_filename = 0;
int have_lineno = 0;
+ char *filename = 0;
/* XXX -- do all the additional formatting with filename and
lineno here */
- have_filename = (self->filename != NULL) &&
- PyString_Check(self->filename);
+ if (self->filename) {
+ if (PyString_Check(self->filename))
+ filename = PyString_AsString(self->filename);
+ else if (PyUnicode_Check(self->filename))
+ filename = PyUnicode_AsString(self->filename);
+ }
have_lineno = (self->lineno != NULL) && PyInt_CheckExact(self->lineno);
- if (!have_filename && !have_lineno)
+ if (!filename && !have_lineno)
return PyObject_Unicode(self->msg ? self->msg : Py_None);
- if (have_filename && have_lineno)
+ if (filename && have_lineno)
return PyUnicode_FromFormat("%S (%s, line %ld)",
self->msg ? self->msg : Py_None,
- my_basename(PyString_AS_STRING(self->filename)),
+ my_basename(filename),
PyInt_AsLong(self->lineno));
- else if (have_filename)
+ else if (filename)
return PyUnicode_FromFormat("%S (%s)",
self->msg ? self->msg : Py_None,
- my_basename(PyString_AS_STRING(self->filename)));
+ my_basename(filename));
else /* only have_lineno */
return PyUnicode_FromFormat("%S (line %ld)",
self->msg ? self->msg : Py_None,
diff --git a/Python/modsupport.c b/Python/modsupport.c
index 330da5f..d29fe9b 100644
--- a/Python/modsupport.c
+++ b/Python/modsupport.c
@@ -387,7 +387,7 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags)
{
char p[1];
p[0] = (char)va_arg(*p_va, int);
- return PyString_FromStringAndSize(p, 1);
+ return PyUnicode_FromStringAndSize(p, 1);
}
case 'C':
{
@@ -438,7 +438,7 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags)
}
n = (Py_ssize_t)m;
}
- v = PyString_FromStringAndSize(str, n);
+ v = PyUnicode_FromStringAndSize(str, n);
}
return v;
}