[FIX] fields.binary: allow writing base64 unicode string values
authorOlivier Dony <odo@openerp.com>
Wed, 22 Feb 2012 09:39:37 +0000 (10:39 +0100)
committerOlivier Dony <odo@openerp.com>
Wed, 22 Feb 2012 09:39:37 +0000 (10:39 +0100)
The fields.binary type allows storing arbitrary
byte arrays, but it has been used historically
to store base64-encoded versions of the binaries.
This was partially related to the way these binary
values are serialized when transferred using the
standard XML-RPC protocol.
With the introduction of JSON-based RPC calls
alongside the 6.1 web client, these base64-encoded
binaries may now be deserialized as unicode ASCII
strings instead of 8-bit strings. That seems like
an acceptable behavior and we can simply coerce
these unicode strings to bytes strings as we know
they will be pure ASCII. Any non-ASCII unicode
value for binary field makes no sense and should
be passed as a byte string directly.

Thanks to Rui Barreiros for providing the final
hint in bug 919982 comments that lead to the
identification of this bug.

lp bug: https://launchpad.net/bugs/899794 fixed

bzr revid: odo@openerp.com-20120222093937-quifmtsfc9gaa9ar

openerp/osv/fields.py

index 7c1761a..bb654ca 100644 (file)
@@ -364,7 +364,15 @@ class time(_column):
 class binary(_column):
     _type = 'binary'
     _symbol_c = '%s'
-    _symbol_f = lambda symb: symb and Binary(symb) or None
+
+    # Binary values may be byte strings (python 2.6 byte array), but
+    # the legacy OpenERP convention is to transfer and store binaries
+    # as base64-encoded strings. The base64 string may be provided as a
+    # unicode in some circumstances, hence the str() cast in symbol_f.
+    # This str coercion will only work for pure ASCII unicode strings,
+    # on purpose - non base64 data must be passed as a 8bit byte strings.
+    _symbol_f = lambda symb: symb and Binary(str(symb)) or None
+
     _symbol_set = (_symbol_c, _symbol_f)
     _symbol_get = lambda self, x: x and str(x)