Use bytes and bytearray for Binary
issue4637 review11091002
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
* Use bytes and bytearray for Binary
|
||||
* Add button_change
|
||||
* Add support for PyPy
|
||||
* Add support for psycopg2cffi
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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)))
|
||||
|
||||
|
||||
@@ -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), '')
|
||||
|
||||
@@ -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
@@ -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):
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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),
|
||||
'')
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -697,7 +697,7 @@ class BinaryDefault(ModelSQL):
|
||||
|
||||
@staticmethod
|
||||
def default_binary():
|
||||
return buffer('default')
|
||||
return b'default'
|
||||
|
||||
|
||||
class BinaryRequired(ModelSQL):
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user