From 1a7c75b1cfc04a0d0f311fa88c77a123e212306f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Valyi?= Date: Wed, 11 Dec 2013 14:08:01 -0200 Subject: [PATCH 1/6] [ADD] web_context_tunnel module, the best tunnel since SSH tunnels? --- web_context_tunnel/__init__.py | 0 web_context_tunnel/__openerp__.py | 40 +++++++++++++++++++ .../static/src/js/context_tunnel.js | 27 +++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 web_context_tunnel/__init__.py create mode 100644 web_context_tunnel/__openerp__.py create mode 100644 web_context_tunnel/static/src/js/context_tunnel.js diff --git a/web_context_tunnel/__init__.py b/web_context_tunnel/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/web_context_tunnel/__openerp__.py b/web_context_tunnel/__openerp__.py new file mode 100644 index 000000000..624db70c6 --- /dev/null +++ b/web_context_tunnel/__openerp__.py @@ -0,0 +1,40 @@ +{ + 'name': 'Web Context Tunnel', + 'category': 'Hidden', + 'author': 'Akretion', + 'license': 'AGPL-3', + 'description':""" +Web Context Tunnel. +=================== + +The problem with OpenERP on_changes +----------------------------------- + +OpenERP uses to pass on_change Ajax events arguments using positional arguments. This is annoying as modules often need to pass extra arguments that are not present in the base on_change signatures. As soon as two modules try to alter this signature to add their extra arguments, they are incompatible between them unless some extra glue module make them compatible again by taking all extra arguments into account. But this leads to a combinatorial explosion to make modules compatibles. + +The solution +------------ + +This module provides a simple work around that will work in most of the cases. In fact it works if the base on_change is designed to pass the context argument. Else it won't work and you should go the old way. But in any case it's a bad practice if an on_change doesn't pass the context argument and you can certainly rant about these bad on_changes to the the context added in the arguments. + +So for an on_change passing the context, how does this module works? + +Well OpenERP already has an elegant solution for an extension module to alter an XML attributes: put an extension poi +nt in the view using position="attributes" and then redefine the attribute. That is already used at several places to replace the "context" attribute that the client will send to the server. + +The idea here is to wrap the extra arguments needed by your on_change inside that context dictionary just as it were a regular Python kwargs. In the on_change override chain, the context is then propagated naturally, no matter of the module order and without any need to hack any on_change signature. + +The issue with just position="attributes" and redefining the context, is that again, if two independent modules do it, they are incompatible unless a third module accounts for both of them. + +But with this module, an extension point can now use position="attributes" and instead of redefining the "context" attribute, you will now just define a new "context_foo" attribute. This module modifies the web client in such a way that before sending the Ajax on_change event request to the server, all the node attributes starting with "context" are merged into a single context dictionnary, keeping the keys and values from all extensions. In the rare case a module really wants to override the value in context, then it needs to still override the original context attribute (or the other original attribute). + +Ad of course, if you should call your on_change by API or webservice instead of using the web client, simply ensure y +u are wrapping the required extra arguments in the context dictionary. +""", + 'version': '2.0', + 'depends': ['web'], + 'js': ['static/src/js/context_tunnel.js'], + 'css': [], + 'auto_install': False, + 'web_preload': False, +} diff --git a/web_context_tunnel/static/src/js/context_tunnel.js b/web_context_tunnel/static/src/js/context_tunnel.js new file mode 100644 index 000000000..fbf7d7260 --- /dev/null +++ b/web_context_tunnel/static/src/js/context_tunnel.js @@ -0,0 +1,27 @@ +openerp.web_context_tunnel = function(instance) { + + instance.web.form.FormWidget.prototype.build_context = function() { + var v_context = false; + var fields_values = false; + console.log(this.node.attrs); + // instead of using just the attr context, we merge any attr starting with context + for (var key in this.node.attrs) { + if (key.substring(0, 7) === "context") { + if (!v_context) { + fields_values = this.field_manager.build_eval_context(); + v_context = new instance.web.CompoundContext(this.node.attrs[key]).set_eval_context(fields_values); + } else { + v_context = new instance.web.CompoundContext(this.node.attrs[key], v_context).set_eval_context(fields_values); + } + + } + } + if (!v_context) { + v_context = (this.field || {}).context || {}; + } + return v_context; + }; +}; + + +// vim:et fdc=0 fdl=0: From b35223f9d48c9c4dc852eb58abd7ea05415b066c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Valyi?= Date: Wed, 11 Dec 2013 14:20:21 -0200 Subject: [PATCH 2/6] [web_context_tunnel] more explicit usage description --- web_context_tunnel/__openerp__.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/web_context_tunnel/__openerp__.py b/web_context_tunnel/__openerp__.py index 624db70c6..336bb7996 100644 --- a/web_context_tunnel/__openerp__.py +++ b/web_context_tunnel/__openerp__.py @@ -26,10 +26,11 @@ The idea here is to wrap the extra arguments needed by your on_change inside tha The issue with just position="attributes" and redefining the context, is that again, if two independent modules do it, they are incompatible unless a third module accounts for both of them. -But with this module, an extension point can now use position="attributes" and instead of redefining the "context" attribute, you will now just define a new "context_foo" attribute. This module modifies the web client in such a way that before sending the Ajax on_change event request to the server, all the node attributes starting with "context" are merged into a single context dictionnary, keeping the keys and values from all extensions. In the rare case a module really wants to override the value in context, then it needs to still override the original context attribute (or the other original attribute). +But with this module, an extension point can now use position="attributes" and instead of redefining the "context" attribute, you will now just define a new "context_foo" attribute this way: {'my_extra_field': my_extra_field}. -Ad of course, if you should call your on_change by API or webservice instead of using the web client, simply ensure y -u are wrapping the required extra arguments in the context dictionary. +This module modifies the web client in such a way that before sending the Ajax on_change event request to the server, all the node attributes starting with "context" are merged into a single context dictionnary, keeping the keys and values from all extensions. In the rare case a module really wants to override the value in context, then it needs to still override the original context attribute (or the other original attribute). + +Ad of course, if you should call your on_change by API or webservice instead of using the web client, simply ensure you are wrapping the required extra arguments in the context dictionary. """, 'version': '2.0', 'depends': ['web'], From 8233f30596c0658c12fa08f9ecae0efe6dd27b8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Valyi?= Date: Wed, 11 Dec 2013 14:55:31 -0200 Subject: [PATCH 3/6] [web_context_tunnel] wrapped description and fixed typo --- web_context_tunnel/__openerp__.py | 47 +++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/web_context_tunnel/__openerp__.py b/web_context_tunnel/__openerp__.py index 336bb7996..8cfdeb1bc 100644 --- a/web_context_tunnel/__openerp__.py +++ b/web_context_tunnel/__openerp__.py @@ -10,27 +10,56 @@ Web Context Tunnel. The problem with OpenERP on_changes ----------------------------------- -OpenERP uses to pass on_change Ajax events arguments using positional arguments. This is annoying as modules often need to pass extra arguments that are not present in the base on_change signatures. As soon as two modules try to alter this signature to add their extra arguments, they are incompatible between them unless some extra glue module make them compatible again by taking all extra arguments into account. But this leads to a combinatorial explosion to make modules compatibles. +OpenERP uses to pass on_change Ajax events arguments using positional +arguments. This is annoying as modules often need to pass extra arguments +that are not present in the base on_change signatures. As soon as two modules +try to alter this signature to add their extra arguments, they are incompatible +between them unless some extra glue module make them compatible again by +taking all extra arguments into account. But this leads to a combinatorial +explosion to make modules compatibles. The solution ------------ -This module provides a simple work around that will work in most of the cases. In fact it works if the base on_change is designed to pass the context argument. Else it won't work and you should go the old way. But in any case it's a bad practice if an on_change doesn't pass the context argument and you can certainly rant about these bad on_changes to the the context added in the arguments. +This module provides a simple work around that will work in most of the cases. +In fact it works if the base on_change is designed to pass the context +argument. Else it won't work and you should go the old way. But in any case +it's a bad practice if an on_change doesn't pass the context argument and you +can certainly rant about these bad on_changes to the the context added in the +arguments. So for an on_change passing the context, how does this module works? -Well OpenERP already has an elegant solution for an extension module to alter an XML attributes: put an extension poi -nt in the view using position="attributes" and then redefine the attribute. That is already used at several places to replace the "context" attribute that the client will send to the server. +Well OpenERP already has an elegant solution for an extension module to alter +an XML attributes: put an extension point in the view using +position="attributes" and then redefine the attribute. That is already used at +several places to replace the "context" attribute that the client will send to +the server. -The idea here is to wrap the extra arguments needed by your on_change inside that context dictionary just as it were a regular Python kwargs. In the on_change override chain, the context is then propagated naturally, no matter of the module order and without any need to hack any on_change signature. +The idea here is to wrap the extra arguments needed by your on_change inside +that context dictionary just as it were a regular Python kwargs. In the +on_change override chain, the context is then propagated naturally, no matter +of the module order and without any need to hack any on_change signature. -The issue with just position="attributes" and redefining the context, is that again, if two independent modules do it, they are incompatible unless a third module accounts for both of them. +The issue with just position="attributes" and redefining the context, is that +again, if two independent modules do it, they are incompatible unless a third +module accounts for both of them. -But with this module, an extension point can now use position="attributes" and instead of redefining the "context" attribute, you will now just define a new "context_foo" attribute this way: {'my_extra_field': my_extra_field}. +But with this module, an extension point can now use position="attributes" and +instead of redefining the "context" attribute, you will now just define a new +"context_foo" attribute this way: +{'my_extra_field': my_extra_field}. -This module modifies the web client in such a way that before sending the Ajax on_change event request to the server, all the node attributes starting with "context" are merged into a single context dictionnary, keeping the keys and values from all extensions. In the rare case a module really wants to override the value in context, then it needs to still override the original context attribute (or the other original attribute). +This module modifies the web client in such a way that before sending the Ajax +on_change event request to the server, all the node attributes starting with +"context" are merged into a single context dictionnary, keeping the keys and +values from all extensions. In the rare case a module really wants to override +the value in context, then it needs to still override the original context +attribute (or the other original attribute). -Ad of course, if you should call your on_change by API or webservice instead of using the web client, simply ensure you are wrapping the required extra arguments in the context dictionary. +And of course, if you should call your on_change by API or webservice instead +of using the web client, simply ensure you are wrapping the required extra +arguments in the context dictionary. """, 'version': '2.0', 'depends': ['web'], From af7a5ccbe943fc48bbb315063f51c921303ac881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Valyi?= Date: Thu, 26 Dec 2013 14:23:00 -0200 Subject: [PATCH 4/6] removing trash console.log --- web_context_tunnel/static/src/js/context_tunnel.js | 1 - 1 file changed, 1 deletion(-) diff --git a/web_context_tunnel/static/src/js/context_tunnel.js b/web_context_tunnel/static/src/js/context_tunnel.js index fbf7d7260..0bbc924ec 100644 --- a/web_context_tunnel/static/src/js/context_tunnel.js +++ b/web_context_tunnel/static/src/js/context_tunnel.js @@ -3,7 +3,6 @@ openerp.web_context_tunnel = function(instance) { instance.web.form.FormWidget.prototype.build_context = function() { var v_context = false; var fields_values = false; - console.log(this.node.attrs); // instead of using just the attr context, we merge any attr starting with context for (var key in this.node.attrs) { if (key.substring(0, 7) === "context") { From b7d3b334c7470ac25c1cf11c0a0f02773555f303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Valyi?= Date: Thu, 26 Dec 2013 14:25:00 -0200 Subject: [PATCH 5/6] 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 --- web_context_tunnel/__openerp__.py | 34 +++++++++++++++---- .../static/test/context_tunnel.js | 14 ++++++++ 2 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 web_context_tunnel/static/test/context_tunnel.js diff --git a/web_context_tunnel/__openerp__.py b/web_context_tunnel/__openerp__.py index 8cfdeb1bc..41519b664 100644 --- a/web_context_tunnel/__openerp__.py +++ b/web_context_tunnel/__openerp__.py @@ -16,7 +16,7 @@ that are not present in the base on_change signatures. As soon as two modules try to alter this signature to add their extra arguments, they are incompatible between them unless some extra glue module make them compatible again by taking all extra arguments into account. But this leads to a combinatorial -explosion to make modules compatibles. +explosion to make modules compatible again. The solution ------------ @@ -37,13 +37,14 @@ several places to replace the "context" attribute that the client will send to the server. The idea here is to wrap the extra arguments needed by your on_change inside -that context dictionary just as it were a regular Python kwargs. In the -on_change override chain, the context is then propagated naturally, no matter -of the module order and without any need to hack any on_change signature. +that context dictionary just as it were a regular Python kwargs. That context +should then be automatically propagated accross the on_change call chain, +no matter of the module order and without any need to hack any on_change +signature. The issue with just position="attributes" and redefining the context, is that -again, if two independent modules do it, they are incompatible unless a third -module accounts for both of them. +again, if two independent modules redefine the context, they are incompatible +unless a third module accounts for both of them. But with this module, an extension point can now use position="attributes" and instead of redefining the "context" attribute, you will now just define a new @@ -60,10 +61,31 @@ attribute (or the other original attribute). And of course, if you should call your on_change by API or webservice instead of using the web client, simply ensure you are wrapping the required extra arguments in the context dictionary. + +Tests +----- + +This module comes with a simple test in static/test/context_tunnel.js. +To run it, open the page /web/tests?mod=web_context_tunnel in your browser +as explained here https://doc.openerp.com/trunk/web/testing +It should also by picked by the Python testing when testing with PhantomJS. + +As for testing modules using web_context_tunnel with YAML, yes it's possible. +In fact you need to manually mimic the new web-client behavior by manually +ensuring you add the extra context keys you will need later in your on_change. +For instance, before the on_change is called, you can alter the context with +a !python statement like context.update({'my_extra_field': my_extra_field}). + +You can see an example of module conversion to use web_context_tunnel here +for instance: +https://github.com/openerpbrasil/l10n_br_core/compare/develop...feature%2Fsale-web-context-tunnel """, 'version': '2.0', 'depends': ['web'], 'js': ['static/src/js/context_tunnel.js'], + 'test': [ + 'static/test/context_tunnel.js', + ], 'css': [], 'auto_install': False, 'web_preload': False, diff --git a/web_context_tunnel/static/test/context_tunnel.js b/web_context_tunnel/static/test/context_tunnel.js new file mode 100644 index 000000000..83e627cf5 --- /dev/null +++ b/web_context_tunnel/static/test/context_tunnel.js @@ -0,0 +1,14 @@ +openerp.testing.section('context_tunnel', { +}, function (test) { + test.dependencies = window['oe_all_dependencies']; + test("context composition", function (instance) { + var field_manager = new instance.web.form.DefaultFieldManager(); + var node = {'attrs': {'context': {'key1': 'value1', 'key2': 'value2'}, 'context_2': {'key3': 'value3'}, 'context_3': {'key4': 'value4'}}} + var w = new instance.web.form.FormWidget(field_manager, node); + var context = w.build_context().eval(); + ok(context['key1'] === 'value1', 'right value for key1 in context'); + ok(context['key2'] === 'value2', 'right value for key2 in context'); + ok(context['key3'] === 'value3', 'right value for key3 in context'); + ok(context['key4'] === 'value4', 'right value for key3 in context'); + }); +}); From 82b9afc00af0a88528ff36746722cbe539f5cebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Valyi?= Date: Thu, 26 Dec 2013 14:43:22 -0200 Subject: [PATCH 6/6] fixed tipo in test logs --- web_context_tunnel/static/test/context_tunnel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_context_tunnel/static/test/context_tunnel.js b/web_context_tunnel/static/test/context_tunnel.js index 83e627cf5..f0fab997c 100644 --- a/web_context_tunnel/static/test/context_tunnel.js +++ b/web_context_tunnel/static/test/context_tunnel.js @@ -9,6 +9,6 @@ openerp.testing.section('context_tunnel', { ok(context['key1'] === 'value1', 'right value for key1 in context'); ok(context['key2'] === 'value2', 'right value for key2 in context'); ok(context['key3'] === 'value3', 'right value for key3 in context'); - ok(context['key4'] === 'value4', 'right value for key3 in context'); + ok(context['key4'] === 'value4', 'right value for key4 in context'); }); });