Use bytes and bytearray for Binary

issue4637
review11091002
This commit is contained in:
Cédric Krier
2015-03-16 19:28:34 +01:00
parent ad5eb3ed97
commit 5cfde31ed2
15 changed files with 67 additions and 51 deletions
+1
View File
@@ -1,3 +1,4 @@
* Use bytes and bytearray for Binary
* Add button_change
* Add support for PyPy
* Add support for psycopg2cffi
+1 -1
View File
@@ -383,7 +383,7 @@ Binary
.. class:: Binary(string[, \**options])
A binary field. It will be represented in Python by a ``str`` instance.
A binary field. It will be represented in Python by a ``bytes`` instance.
:class:`Binary` has one extra optional argument:
+1 -1
View File
@@ -421,7 +421,7 @@ class Cursor(CursorInterface):
sqlite.register_converter('NUMERIC', lambda val: Decimal(val))
if sys.version_info[0] == 2:
sqlite.register_adapter(Decimal, lambda val: buffer(str(val)))
sqlite.register_adapter(Decimal, lambda val: bytearray(str(val)))
else:
sqlite.register_adapter(Decimal, lambda val: bytes(str(val)))
+4 -3
View File
@@ -533,7 +533,8 @@ class ActionReport(ActionMixin, ModelSQL, ModelView):
limit=limit, offset=offset))
for report_id, report in cursor.fetchall():
if report:
report = buffer(base64.decodestring(str(report)))
report = fields.Binary.cast(
base64.decodestring(bytes(report)))
cursor.execute(*action_report.update(
[action_report.report_content_custom],
[report],
@@ -592,7 +593,7 @@ class ActionReport(ActionMixin, ModelSQL, ModelView):
@classmethod
def get_report_content(cls, reports, name):
contents = {}
converter = buffer
converter = fields.Binary.cast
default = None
format_ = Transaction().context.pop('%s.%s'
% (cls.__name__, name), '')
@@ -624,7 +625,7 @@ class ActionReport(ActionMixin, ModelSQL, ModelView):
@classmethod
def get_style_content(cls, reports, name):
contents = {}
converter = buffer
converter = fields.Binary.cast
default = None
format_ = Transaction().context.pop('%s.%s'
% (cls.__name__, name), '')
+1 -1
View File
@@ -130,7 +130,7 @@ class Attachment(ModelSQL, ModelView):
else:
try:
with open(filename, 'rb') as file_p:
value = buffer(file_p.read())
value = fields.Binary.cast(file_p.read())
except IOError:
pass
return value
+1 -1
View File
@@ -1009,7 +1009,7 @@ class ModelGraph(Report):
graph.set('ratio', 'auto')
cls.fill_graph(models, graph, level=data['level'], filter=filter)
data = graph.create(prog='dot', format='png')
return ('png', buffer(data), False, action_report.name)
return ('png', fields.Binary.cast(data), False, action_report.name)
@classmethod
def fill_graph(cls, models, graph, level=1, filter=None):
+1 -2
View File
@@ -1616,9 +1616,8 @@ class TranslationExport(Wizard):
def transition_export(self):
pool = Pool()
Translation = pool.get('ir.translation')
file_data = Translation.translation_export(
self.result.file = Translation.translation_export(
self.start.language.code, self.start.module.name)
self.result.file = buffer(file_data) if file_data else None
return 'result'
def default_result(self, fields):
+6 -5
View File
@@ -9,9 +9,10 @@ from ... import backend
class Binary(Field):
'''
Define a binary field (``str``).
Define a binary field (``bytes``).
'''
_type = 'binary'
cast = bytearray if bytes == str else bytes
def __init__(self, string='', help='', required=False, readonly=False,
domain=None, states=None, select=False, on_change=None,
@@ -28,10 +29,10 @@ class Binary(Field):
select=select, on_change=on_change, on_change_with=on_change_with,
depends=depends, context=context, loading=loading)
@staticmethod
def get(ids, model, name, values=None):
@classmethod
def get(cls, ids, model, name, values=None):
'''
Convert the binary value into ``str``
Convert the binary value into ``bytes``
:param ids: a list of ids
:param model: a string with the name of the model
@@ -42,7 +43,7 @@ class Binary(Field):
if values is None:
values = {}
res = {}
converter = buffer
converter = cls.cast
default = None
format_ = Transaction().context.pop('%s.%s' % (model.__name__, name),
'')
+4 -1
View File
@@ -279,7 +279,10 @@ def dump(database_name, password):
data = Database.dump(database_name)
logger.info('DUMP DB: %s', database_name)
return buffer(data)
if bytes == str:
return bytearray(data)
else:
return bytes(data)
def restore(database_name, password, data, update=False):
+12 -7
View File
@@ -57,8 +57,12 @@ JSONDecoder.register('time',
dct['microsecond']))
JSONDecoder.register('timedelta',
lambda dct: datetime.timedelta(seconds=dct['seconds']))
JSONDecoder.register('buffer', lambda dct:
buffer(base64.decodestring(dct['base64'])))
def _bytes_decoder(dct):
cast = bytearray if bytes == str else bytes
return cast(base64.decodestring(dct['base64']))
JSONDecoder.register('bytes', _bytes_decoder)
JSONDecoder.register('Decimal', lambda dct: Decimal(dct['decimal']))
@@ -112,11 +116,12 @@ JSONEncoder.register(datetime.timedelta,
'__class__': 'timedelta',
'seconds': o.total_seconds(),
})
JSONEncoder.register(buffer,
lambda o: {
'__class__': 'buffer',
'base64': base64.encodestring(o),
})
_bytes_encoder = lambda o: {
'__class__': 'bytes',
'base64': base64.encodestring(o),
}
JSONEncoder.register(bytes, _bytes_encoder)
JSONEncoder.register(bytearray, _bytes_encoder)
JSONEncoder.register(Decimal,
lambda o: {
'__class__': 'Decimal',
+5 -4
View File
@@ -10,7 +10,6 @@ import SimpleXMLRPCServer
import SocketServer
import xmlrpclib
import socket
import sys
import base64
import datetime
from types import DictType
@@ -29,7 +28,7 @@ def dump_decimal(self, value, write):
self.dump_struct(value, write)
def dump_buffer(self, value, write):
def dump_bytes(self, value, write):
self.write = write
value = xmlrpclib.Binary(value)
value.encode(self)
@@ -67,7 +66,8 @@ xmlrpclib.Marshaller.dispatch[type(None)] = \
xmlrpclib.Marshaller.dispatch[datetime.date] = dump_date
xmlrpclib.Marshaller.dispatch[datetime.time] = dump_time
xmlrpclib.Marshaller.dispatch[datetime.timedelta] = dump_timedelta
xmlrpclib.Marshaller.dispatch[buffer] = dump_buffer
xmlrpclib.Marshaller.dispatch[bytes] = dump_bytes
xmlrpclib.Marshaller.dispatch[bytearray] = dump_bytes
def dump_struct(self, value, write, escape=xmlrpclib.escape):
@@ -132,7 +132,8 @@ xmlrpclib.Unmarshaller.dispatch["dateTime.iso8601"] = _end_dateTime
def _end_base64(self, data):
value = xmlrpclib.Binary()
value.decode(data)
self.append(buffer(value.data))
cast = bytearray if bytes == str else bytes
self.append(cast(value.data))
self._value = 0
xmlrpclib.Unmarshaller.dispatch['base64'] = _end_base64
+8 -8
View File
@@ -147,8 +147,8 @@ class Report(URLMixin, PoolBase):
report_context = cls.get_context(records, data)
oext, content = cls.convert(action_report,
cls.render(action_report, report_context))
return (oext, buffer(content), action_report.direct_print,
action_report.name)
content = bytearray(content) if bytes == str else bytes(content)
return (oext, content, action_report.direct_print, action_report.name)
@classmethod
def _get_records(cls, ids, model, data):
@@ -196,11 +196,11 @@ class Report(URLMixin, PoolBase):
@classmethod
def _prepare_template_file(cls, report):
# Convert to str as buffer from DB is not supported by StringIO
report_content = (str(report.report_content) if report.report_content
else False)
style_content = (str(report.style_content) if report.style_content
else False)
# Convert to str as value from DB is not supported by StringIO
report_content = (bytes(report.report_content) if report.report_content
else None)
style_content = (bytes(report.style_content) if report.style_content
else None)
if not report_content:
raise Exception('Error', 'Missing report file!')
@@ -269,7 +269,7 @@ class Report(URLMixin, PoolBase):
outzip.writestr(file, picture)
if manifest:
outzip.writestr(MANIFEST, str(manifest))
outzip.writestr(MANIFEST, bytes(manifest))
content_z.close()
content_io.close()
+1 -1
View File
@@ -697,7 +697,7 @@ class BinaryDefault(ModelSQL):
@staticmethod
def default_binary():
return buffer('default')
return b'default'
class BinaryRequired(ModelSQL):
+13 -10
View File
@@ -16,6 +16,7 @@ from trytond.tests.test_tryton import POOL, DB_NAME, USER, CONTEXT, \
install_module
from trytond.transaction import Transaction
from trytond.exceptions import UserError
from trytond.model import fields
class FieldsTestCase(unittest.TestCase):
@@ -3190,32 +3191,34 @@ class FieldsTestCase(unittest.TestCase):
with Transaction().start(DB_NAME, USER,
context=CONTEXT) as transaction:
bin1, = self.binary.create([{
'binary': buffer('foo'),
'binary': fields.Binary.cast(b'foo'),
}])
self.assert_(bin1.binary == buffer('foo'))
self.assert_(bin1.binary == fields.Binary.cast(b'foo'))
self.binary.write([bin1], {'binary': buffer('bar')})
self.assert_(bin1.binary == buffer('bar'))
self.binary.write([bin1], {'binary': fields.Binary.cast(b'bar')})
self.assert_(bin1.binary == fields.Binary.cast(b'bar'))
with transaction.set_context({'test.binary.binary': 'size'}):
bin1_size = self.binary(bin1.id)
self.assert_(bin1_size.binary == len('bar'))
self.assert_(bin1_size.binary != buffer('bar'))
self.assert_(bin1_size.binary == len(b'bar'))
self.assert_(bin1_size.binary != fields.Binary.cast(b'bar'))
bin2, = self.binary.create([{}])
self.assert_(bin2.binary is None)
bin3, = self.binary_default.create([{}])
self.assert_(bin3.binary == buffer('default'))
self.assert_(bin3.binary == fields.Binary.cast(b'default'))
self.assertRaises(UserError, self.binary_required.create, [{}])
transaction.cursor.rollback()
bin4, = self.binary_required.create([{'binary': buffer('baz')}])
self.assert_(bin4.binary == buffer('baz'))
bin4, = self.binary_required.create([{
'binary': fields.Binary.cast(b'baz'),
}])
self.assert_(bin4.binary == fields.Binary.cast(b'baz'))
self.assertRaises(UserError, self.binary_required.create,
[{'binary': buffer('')}])
[{'binary': fields.Binary.cast(b'')}])
transaction.cursor.rollback()
+8 -6
View File
@@ -30,9 +30,10 @@ class JSONTestCase(unittest.TestCase):
'Test time'
self.dumps_loads(datetime.datetime.now().time())
def test_buffer(self):
'Test buffer'
self.dumps_loads(buffer('foo'))
def test_bytes(self):
'Test bytes'
self.dumps_loads(bytes(b'foo'))
self.dumps_loads(bytearray(b'foo'))
def test_decimal(self):
'Test Decimal'
@@ -52,9 +53,10 @@ class XMLTestCase(unittest.TestCase):
'Test Decimal'
self.dumps_loads(Decimal('3.141592653589793'))
def test_buffer(self):
'Test buffer'
self.dumps_loads(buffer('foo'))
def test_bytes(self):
'Test bytes'
self.dumps_loads(bytes(b'foo'))
self.dumps_loads(bytearray(b'foo'))
def test_date(self):
'Test date'