Merge lp:~akretion-team/server-env-tools/web-context-tunnel into lp:~server-env-tools-core-editors/server-env-tools/7.0

Proposed by Raphaël Valyi - http://www.akretion.com
Status: Merged
Approved by: Alexandre Fayolle - camptocamp
Approved revision: 57
Merged at revision: 56
Proposed branch: lp:~akretion-team/server-env-tools/web-context-tunnel
Merge into: lp:~server-env-tools-core-editors/server-env-tools/7.0
Diff against target: 153 lines (+132/-0)
3 files modified
web_context_tunnel/__openerp__.py (+92/-0)
web_context_tunnel/static/src/js/context_tunnel.js (+26/-0)
web_context_tunnel/static/test/context_tunnel.js (+14/-0)
To merge this branch: bzr merge lp:~akretion-team/server-env-tools/web-context-tunnel
Reviewer Review Type Date Requested Status
Guewen Baconnier @ Camptocamp code review Approve
Alexandre Fayolle - camptocamp code review, no test Approve
Mario Arias (community) code review, no test Approve
Alexis de Lattre (community) Approve
Review via email: mp+198599@code.launchpad.net

Description of the change

please see the module description in the __openerp__.py file.

I would like to see if OCA could not use that to avoid changing on_change signatures in incompatible ways for the OCA modules.

Eager to look after your comments.

To post a comment you must log in.
53. By Raphaël Valyi - http://www.akretion.com

[web_context_tunnel] more explicit usage description

Revision history for this message
Raphaël Valyi - http://www.akretion.com (rvalyi) wrote :

To help for the review, it's probably helpful to mention that the original build_context method is defined this way:
https://github.com/akretion/openerp-web/blob/ocb-7.0/addons/web/static/src/js/view_form.js#L1866

Also, I'm redefining build_context on the prototype directly (instead of using .extend), because we want to alter the build_context of all widget built upon the instance.web.form.FormWidget prototype.

Notice that my module totally preserves the original behavior if a widget simply has a context attribute with no extra context* extensions.

Revision history for this message
Alexandre Fayolle - camptocamp (alexandre-fayolle-c2c) wrote :

could you please:

* wrap the lines in __openerp__.py
* line 28-29: fix the newline
* line 39: s/Ad/And/

review: Needs Fixing (code review, no test)
54. By Raphaël Valyi - http://www.akretion.com

[web_context_tunnel] wrapped description and fixed typo

Revision history for this message
Raphaël Valyi - http://www.akretion.com (rvalyi) wrote :

@Alexandre Fayolle

Done. How is it now? Thanks.

Revision history for this message
Alexis de Lattre (alexis-via) wrote :

This is a great workaround for a very very annoying problem of OpenERP : 2 modules inherit the same on_change to add arguments and it makes the 2 modules incompatible. Almost all experienced OpenERP developers were already confronted to this headache. This seems a clever and lightweight solution.

I am not a JS developer so I can't give my opinion on the code itself, but it approve this from an OpenERP module developer point of view.

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

It could deserve a test.

You should remove the console.log()

What about the yaml tests? They use the views to apply automatically the onchanges, so the tests will fail because they won't take the extra attributes in account.

review: Needs Fixing
Revision history for this message
Raphaël Valyi - http://www.akretion.com (rvalyi) wrote :

Hello Guewen,

sorry about the console.log, removing it.
You made an interesting point about the on_change.
In fact only tests testing modules with the extra fields may fail, not the existing base tests.

Are there so many of such tests? (but yeah lack of test is not a terribly good reason anyway).
Eventually, in OCB, we could modularize the on_change test player so this module have a chance to alter it properly. Then our module will keep being compatible with the commercial branch but at least tests will be properly executed in the OCB branch? Not sure, just thinking...

55. By Raphaël Valyi - http://www.akretion.com

removing trash console.log

56. By Raphaël Valyi - http://www.akretion.com

adding unit test and explanation about how to run the unit test and also about how to run YAML tests of module using web_context_tunnel

Revision history for this message
Raphaël Valyi - http://www.akretion.com (rvalyi) wrote :

@Guewen,

as you can see with my last commits:

1) I removed the console.log statement
2) I added a web unit tests + instruction on how to run it
3) I added a section explaining how to run standard YAML tests for a module using web_context_tunnel and gave a real example of module conversion for the Brazilian localization (including YAML tests) https://github.com/openerpbrasil/l10n_br_core/compare/develop...feature%2Fsale-web-context-tunnel

So what do you think now?

I think a place we could use it (among many others would be the fiscal-rules) modules, so we could leave the original on_change signatures untouched and retain compatibility with the other modules.

57. By Raphaël Valyi - http://www.akretion.com

fixed tipo in test logs

Revision history for this message
Mario Arias (the-clone-master) wrote :

A great way to avoid signature changes!

When approved, please promote its usage among known community modules with these signature problems... ;-)

review: Approve (code review, no test)
Revision history for this message
Alexandre Fayolle - camptocamp (alexandre-fayolle-c2c) :
review: Approve (code review, no test)
Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

> @Guewen,
>
> as you can see with my last commits:
>
> 1) I removed the console.log statement
> 2) I added a web unit tests + instruction on how to run it
> 3) I added a section explaining how to run standard YAML tests for a module
> using web_context_tunnel and gave a real example of module conversion for the
> Brazilian localization (including YAML tests)
> https://github.com/openerpbrasil/l10n_br_core/compare/develop...feature
> %2Fsale-web-context-tunnel
>
> So what do you think now?
>
> I think a place we could use it (among many others would be the fiscal-rules)
> modules, so we could leave the original on_change signatures untouched and
> retain compatibility with the other modules.

Neat! Thanks

review: Approve (code review)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'web_context_tunnel'
2=== added file 'web_context_tunnel/__init__.py'
3=== added file 'web_context_tunnel/__openerp__.py'
4--- web_context_tunnel/__openerp__.py 1970-01-01 00:00:00 +0000
5+++ web_context_tunnel/__openerp__.py 2013-12-26 16:44:05 +0000
6@@ -0,0 +1,92 @@
7+{
8+ 'name': 'Web Context Tunnel',
9+ 'category': 'Hidden',
10+ 'author': 'Akretion',
11+ 'license': 'AGPL-3',
12+ 'description':"""
13+Web Context Tunnel.
14+===================
15+
16+The problem with OpenERP on_changes
17+-----------------------------------
18+
19+OpenERP uses to pass on_change Ajax events arguments using positional
20+arguments. This is annoying as modules often need to pass extra arguments
21+that are not present in the base on_change signatures. As soon as two modules
22+try to alter this signature to add their extra arguments, they are incompatible
23+between them unless some extra glue module make them compatible again by
24+taking all extra arguments into account. But this leads to a combinatorial
25+explosion to make modules compatible again.
26+
27+The solution
28+------------
29+
30+This module provides a simple work around that will work in most of the cases.
31+In fact it works if the base on_change is designed to pass the context
32+argument. Else it won't work and you should go the old way. But in any case
33+it's a bad practice if an on_change doesn't pass the context argument and you
34+can certainly rant about these bad on_changes to the the context added in the
35+arguments.
36+
37+So for an on_change passing the context, how does this module works?
38+
39+Well OpenERP already has an elegant solution for an extension module to alter
40+an XML attributes: put an extension point in the view using
41+position="attributes" and then redefine the attribute. That is already used at
42+several places to replace the "context" attribute that the client will send to
43+the server.
44+
45+The idea here is to wrap the extra arguments needed by your on_change inside
46+that context dictionary just as it were a regular Python kwargs. That context
47+should then be automatically propagated accross the on_change call chain,
48+no matter of the module order and without any need to hack any on_change
49+signature.
50+
51+The issue with just position="attributes" and redefining the context, is that
52+again, if two independent modules redefine the context, they are incompatible
53+unless a third module accounts for both of them.
54+
55+But with this module, an extension point can now use position="attributes" and
56+instead of redefining the "context" attribute, you will now just define a new
57+"context_foo" attribute this way:
58+<attribute name="context_foo">{'my_extra_field': my_extra_field}</attribute>.
59+
60+This module modifies the web client in such a way that before sending the Ajax
61+on_change event request to the server, all the node attributes starting with
62+"context" are merged into a single context dictionnary, keeping the keys and
63+values from all extensions. In the rare case a module really wants to override
64+the value in context, then it needs to still override the original context
65+attribute (or the other original attribute).
66+
67+And of course, if you should call your on_change by API or webservice instead
68+of using the web client, simply ensure you are wrapping the required extra
69+arguments in the context dictionary.
70+
71+Tests
72+-----
73+
74+This module comes with a simple test in static/test/context_tunnel.js.
75+To run it, open the page /web/tests?mod=web_context_tunnel in your browser
76+as explained here https://doc.openerp.com/trunk/web/testing
77+It should also by picked by the Python testing when testing with PhantomJS.
78+
79+As for testing modules using web_context_tunnel with YAML, yes it's possible.
80+In fact you need to manually mimic the new web-client behavior by manually
81+ensuring you add the extra context keys you will need later in your on_change.
82+For instance, before the on_change is called, you can alter the context with
83+a !python statement like context.update({'my_extra_field': my_extra_field}).
84+
85+You can see an example of module conversion to use web_context_tunnel here
86+for instance:
87+https://github.com/openerpbrasil/l10n_br_core/compare/develop...feature%2Fsale-web-context-tunnel
88+""",
89+ 'version': '2.0',
90+ 'depends': ['web'],
91+ 'js': ['static/src/js/context_tunnel.js'],
92+ 'test': [
93+ 'static/test/context_tunnel.js',
94+ ],
95+ 'css': [],
96+ 'auto_install': False,
97+ 'web_preload': False,
98+}
99
100=== added directory 'web_context_tunnel/i18n'
101=== added directory 'web_context_tunnel/static'
102=== added directory 'web_context_tunnel/static/src'
103=== added directory 'web_context_tunnel/static/src/js'
104=== added file 'web_context_tunnel/static/src/js/context_tunnel.js'
105--- web_context_tunnel/static/src/js/context_tunnel.js 1970-01-01 00:00:00 +0000
106+++ web_context_tunnel/static/src/js/context_tunnel.js 2013-12-26 16:44:05 +0000
107@@ -0,0 +1,26 @@
108+openerp.web_context_tunnel = function(instance) {
109+
110+ instance.web.form.FormWidget.prototype.build_context = function() {
111+ var v_context = false;
112+ var fields_values = false;
113+ // instead of using just the attr context, we merge any attr starting with context
114+ for (var key in this.node.attrs) {
115+ if (key.substring(0, 7) === "context") {
116+ if (!v_context) {
117+ fields_values = this.field_manager.build_eval_context();
118+ v_context = new instance.web.CompoundContext(this.node.attrs[key]).set_eval_context(fields_values);
119+ } else {
120+ v_context = new instance.web.CompoundContext(this.node.attrs[key], v_context).set_eval_context(fields_values);
121+ }
122+
123+ }
124+ }
125+ if (!v_context) {
126+ v_context = (this.field || {}).context || {};
127+ }
128+ return v_context;
129+ };
130+};
131+
132+
133+// vim:et fdc=0 fdl=0:
134
135=== added directory 'web_context_tunnel/static/test'
136=== added file 'web_context_tunnel/static/test/context_tunnel.js'
137--- web_context_tunnel/static/test/context_tunnel.js 1970-01-01 00:00:00 +0000
138+++ web_context_tunnel/static/test/context_tunnel.js 2013-12-26 16:44:05 +0000
139@@ -0,0 +1,14 @@
140+openerp.testing.section('context_tunnel', {
141+}, function (test) {
142+ test.dependencies = window['oe_all_dependencies'];
143+ test("context composition", function (instance) {
144+ var field_manager = new instance.web.form.DefaultFieldManager();
145+ var node = {'attrs': {'context': {'key1': 'value1', 'key2': 'value2'}, 'context_2': {'key3': 'value3'}, 'context_3': {'key4': 'value4'}}}
146+ var w = new instance.web.form.FormWidget(field_manager, node);
147+ var context = w.build_context().eval();
148+ ok(context['key1'] === 'value1', 'right value for key1 in context');
149+ ok(context['key2'] === 'value2', 'right value for key2 in context');
150+ ok(context['key3'] === 'value3', 'right value for key3 in context');
151+ ok(context['key4'] === 'value4', 'right value for key4 in context');
152+ });
153+});