Merge lp:~camptocamp/openerp-connector/7.0-unicode-pickled-1288187 into lp:~openerp-connector-core-editors/openerp-connector/7.0

Proposed by Guewen Baconnier @ Camptocamp
Status: Merged
Approved by: Guewen Baconnier @ Camptocamp
Approved revision: 627
Merged at revision: 627
Proposed branch: lp:~camptocamp/openerp-connector/7.0-unicode-pickled-1288187
Merge into: lp:~openerp-connector-core-editors/openerp-connector/7.0
Diff against target: 112 lines (+51/-4)
5 files modified
connector/__openerp__.py (+1/-1)
connector/migrations/2.2.0/pre-migration.py (+9/-0)
connector/queue/job.py (+2/-2)
connector/queue/model.py (+1/-1)
connector/tests/test_job.py (+38/-0)
To merge this branch: bzr merge lp:~camptocamp/openerp-connector/7.0-unicode-pickled-1288187
Reviewer Review Type Date Requested Status
Leonardo Pistone (community) code review Approve
Stéphane Bidoul (Acsone) (community) code review and test Approve
OpenERP Connector Core Editors Pending
Review via email: mp+209481@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Stéphane Bidoul (Acsone) (sbi) wrote :

LGTM. Binary fields are cleaner and both approaches require migration of existing data.

Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

> LGTM. Binary fields are cleaner and both approaches require migration of
> existing data.

Thanks for your opinion. I added a migration script, can you check if it works for you?

Revision history for this message
Stéphane Bidoul (Acsone) (sbi) wrote :

Works fine. I also tested the migration script.

Thanks for the fast reaction!

review: Approve (code review and test)
Revision history for this message
Leonardo Pistone (lepistone) wrote :

I tried to give a look to the ORM to see if it clearly treats string field contents as unicode, as opposed to utf-8 bytestrings, but that is convoluted to say the least (it uses ustr() from server/openerp/loglevels.py).

Picked data is indeed binary, so I agree, good idea. And indeed it is a good idea to test it

I have a little doubt left: this line from job.py:

    func = _unpickle(str(stored.func)) # openerp stores them as unicode...

Is "str" still necessary?

Moreover, maybe we could add in the test a bytestring parameter with accents.

Thanks!

review: Needs Information (code review)
Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

> I tried to give a look to the ORM to see if it clearly treats string field
> contents as unicode, as opposed to utf-8 bytestrings, but that is convoluted
> to say the least (it uses ustr() from server/openerp/loglevels.py).
>
> Picked data is indeed binary, so I agree, good idea. And indeed it is a good
> idea to test it
>
> I have a little doubt left: this line from job.py:
>
> func = _unpickle(str(stored.func)) # openerp stores them as unicode...
>
> Is "str" still necessary?

Good catch!

>
> Moreover, maybe we could add in the test a bytestring parameter with accents.

You are right, added.

>
> Thanks!

Thanks for your review

Revision history for this message
Leonardo Pistone (lepistone) wrote :

thanks!

review: Approve (code review)
627. By Guewen Baconnier @ Camptocamp

confusing typo

628. By Guewen Baconnier @ Camptocamp

func::bytea can fail to convert the string to bytea because it interprets the backshlashes. Use convert_to to LATIN1 instead

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'connector/__openerp__.py'
2--- connector/__openerp__.py 2014-02-06 10:09:11 +0000
3+++ connector/__openerp__.py 2014-03-19 11:14:05 +0000
4@@ -20,7 +20,7 @@
5 ##############################################################################
6
7 {'name': 'Connector',
8- 'version': '2.1.1',
9+ 'version': '2.2.0',
10 'author': 'Openerp Connector Core Editors',
11 'website': 'http://openerp-connector.com',
12 'license': 'AGPL-3',
13
14=== added directory 'connector/migrations'
15=== added directory 'connector/migrations/2.2.0'
16=== added file 'connector/migrations/2.2.0/pre-migration.py'
17--- connector/migrations/2.2.0/pre-migration.py 1970-01-01 00:00:00 +0000
18+++ connector/migrations/2.2.0/pre-migration.py 2014-03-19 11:14:05 +0000
19@@ -0,0 +1,9 @@
20+# -*- encoding: utf-8 -*-
21+
22+__name__ = "Convert jobs pickled func to bytea"
23+
24+def migrate(cr, version):
25+ if not version:
26+ return
27+ cr.execute("ALTER TABLE queue_job ALTER func "
28+ "TYPE bytea USING convert_to(func, 'LATIN1') ")
29
30=== modified file 'connector/queue/job.py'
31--- connector/queue/job.py 2014-02-04 14:39:23 +0000
32+++ connector/queue/job.py 2014-03-19 11:14:05 +0000
33@@ -65,7 +65,7 @@
34 raised as `NotReadableJobError`).
35 """
36 try:
37- unpickled = loads(pickled.encode('utf-8'))
38+ unpickled = loads(pickled)
39 except (StandardError, UnpicklingError):
40 raise NotReadableJobError('Could not unpickle.', pickled)
41 return unpickled
42@@ -229,7 +229,7 @@
43 self._openerp_id(job_uuid),
44 context=self.session.context)
45
46- func = _unpickle(str(stored.func)) # openerp stores them as unicode...
47+ func = _unpickle(stored.func)
48
49 (func_name, args, kwargs) = func
50
51
52=== modified file 'connector/queue/model.py'
53--- connector/queue/model.py 2013-11-19 10:14:40 +0000
54+++ connector/queue/model.py 2014-03-19 11:14:05 +0000
55@@ -53,7 +53,7 @@
56 'user_id': fields.many2one('res.users', string='User ID', required=True),
57 'name': fields.char('Description', readonly=True),
58 'func_string': fields.char('Task', readonly=True),
59- 'func': fields.text('Pickled Function', readonly=True, required=True),
60+ 'func': fields.binary('Pickled Function', readonly=True, required=True),
61 'state': fields.selection(STATES,
62 string='State',
63 readonly=True,
64
65=== modified file 'connector/tests/test_job.py'
66--- connector/tests/test_job.py 2014-01-13 16:07:35 +0000
67+++ connector/tests/test_job.py 2014-03-19 11:14:05 +0000
68@@ -161,6 +161,44 @@
69 self.assertAlmostEqual(job.eta, job_read.eta,
70 delta=delta)
71
72+ def test_unicode(self):
73+ job = Job(func=dummy_task_args,
74+ model_name='res.users',
75+ args=(u'öô¿‽', u'ñě'),
76+ kwargs={'c': u'ßø'},
77+ priority=15,
78+ description=u"My dé^Wdescription")
79+ job.user_id = 1
80+ storage = OpenERPJobStorage(self.session)
81+ storage.store(job)
82+ job_read = storage.load(job.uuid)
83+ self.assertEqual(job.args, job_read.args)
84+ self.assertEqual(job_read.args, ('res.users', u'öô¿‽', u'ñě'))
85+ self.assertEqual(job.kwargs, job_read.kwargs)
86+ self.assertEqual(job_read.kwargs, {'c': u'ßø'})
87+ self.assertEqual(job.description, job_read.description)
88+ self.assertEqual(job_read.description, u"My dé^Wdescription")
89+
90+ def test_accented_bytestring(self):
91+ job = Job(func=dummy_task_args,
92+ model_name='res.users',
93+ args=('öô¿‽', 'ñě'),
94+ kwargs={'c': 'ßø'},
95+ priority=15,
96+ description="My dé^Wdescription")
97+ job.user_id = 1
98+ storage = OpenERPJobStorage(self.session)
99+ storage.store(job)
100+ job_read = storage.load(job.uuid)
101+ self.assertEqual(job.args, job_read.args)
102+ self.assertEqual(job_read.args, ('res.users', 'öô¿‽', 'ñě'))
103+ self.assertEqual(job.kwargs, job_read.kwargs)
104+ self.assertEqual(job_read.kwargs, {'c': 'ßø'})
105+ # the job's description has been created as bytestring but is
106+ # decoded to utf8 by the ORM so make them comparable
107+ self.assertEqual(job.description, job_read.description.encode('utf8'))
108+ self.assertEqual(job_read.description, "My dé^Wdescription".decode('utf8'))
109+
110 def test_job_delay(self):
111 self.cr.execute('delete from queue_job')
112 deco_task = job(task_a)