Merge lp:~fabien-morin/unifield-web/perf_improvement_web into lp:unifield-web

Proposed by jftempo
Status: Rejected
Rejected by: jftempo
Proposed branch: lp:~fabien-morin/unifield-web/perf_improvement_web
Merge into: lp:unifield-web
Diff against target: 522 lines (+191/-140)
11 files modified
addons/openerp/controllers/attachment.py (+2/-1)
addons/openerp/controllers/modules.py (+0/-13)
addons/openerp/controllers/preferences.py (+2/-1)
addons/openerp/controllers/viewed.py (+1/-1)
addons/openerp/controllers/widgets.py (+1/-1)
addons/openerp/static/javascript/form_state.js (+177/-105)
addons/openerp/utils/utils.py (+2/-2)
addons/openerp/widgets/form/_action.py (+3/-1)
addons/openerp/widgets/form/_form.py (+1/-1)
addons/view_diagram/controllers/process.py (+2/-1)
openobject/controllers/_root.py (+0/-13)
To merge this branch: bzr merge lp:~fabien-morin/unifield-web/perf_improvement_web
Reviewer Review Type Date Requested Status
UniField Reviewer Team Pending
Review via email: mp+303278@code.launchpad.net
To post a comment you must log in.
4810. By Fabien MORIN

US-1246 [MERGE] with latest trunk

Unmerged revisions

4810. By Fabien MORIN

US-1246 [MERGE] with latest trunk

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'addons/openerp/controllers/attachment.py'
2--- addons/openerp/controllers/attachment.py 2016-05-02 12:04:12 +0000
3+++ addons/openerp/controllers/attachment.py 2016-08-26 09:28:44 +0000
4@@ -56,7 +56,8 @@
5 @expose(content_type="application/octet-stream")
6 def get(self, record=False):
7 record = int(record)
8- attachment = rpc.RPCProxy('ir.attachment').read(record, [], rpc.session.context)
9+ attachment = rpc.RPCProxy('ir.attachment').read(record, ['type',
10+ 'datas', 'url', 'name'], rpc.session.context)
11
12 if attachment['type'] == 'binary':
13 cherrypy.response.headers["Content-Disposition"] = 'attachment; filename="%s"' % attachment['name']
14
15=== modified file 'addons/openerp/controllers/modules.py'
16--- addons/openerp/controllers/modules.py 2011-01-18 11:35:00 +0000
17+++ addons/openerp/controllers/modules.py 2016-08-26 09:28:44 +0000
18@@ -14,19 +14,6 @@
19 class ModuleForm(form.Form):
20 _cp_path = "/openerp/modules"
21
22- def has_new_modules(self):
23- """ Returns whether there are new web modules available for download
24- (brand new or updates)
25-
26- :rtype bool:
27- """
28- return bool([
29- name for (name, version) in rpc.RPCProxy('ir.module.module').list_web()
30- if (not addons.exists(name)
31- or version > addons.get_info(name).get('version', '0')
32- or name not in addons._loaded[cherrypy.session.get('db')])
33- ])
34-
35 def get_new_modules(self):
36 if not addons.writeable: return []
37 modules = rpc.RPCProxy('ir.module.module')
38
39=== modified file 'addons/openerp/controllers/preferences.py'
40--- addons/openerp/controllers/preferences.py 2016-07-25 13:13:38 +0000
41+++ addons/openerp/controllers/preferences.py 2016-08-26 09:28:44 +0000
42@@ -52,7 +52,8 @@
43 proxy = rpc.RPCProxy('res.users')
44 action_id = proxy.action_get({})
45
46- action = rpc.RPCProxy('ir.actions.act_window').read([action_id], False, rpc.session.context)[0]
47+ action = rpc.RPCProxy('ir.actions.act_window').read([action_id],
48+ ['views', 'view_id'], rpc.session.context)[0]
49
50 view_ids=[]
51 if action.get('views', []):
52
53=== modified file 'addons/openerp/controllers/viewed.py'
54--- addons/openerp/controllers/viewed.py 2011-01-18 20:49:43 +0000
55+++ addons/openerp/controllers/viewed.py 2016-08-26 09:28:44 +0000
56@@ -289,7 +289,7 @@
57 return doc_src.toxml().replace('\t', '')
58
59 views = rpc.RPCProxy('ir.ui.view')
60- res = views.read([view_id])[0]
61+ res = views.read([view_id], ['arch', 'model', 'type'])[0]
62
63 def _inherit_apply_rec(result, inherit_id):
64 # get all views which inherit from (ie modify) this view
65
66=== modified file 'addons/openerp/controllers/widgets.py'
67--- addons/openerp/controllers/widgets.py 2010-12-02 12:58:19 +0000
68+++ addons/openerp/controllers/widgets.py 2016-08-26 09:28:44 +0000
69@@ -44,7 +44,7 @@
70 ('user_id', '=', False)],
71 0, 0, 0, ctx)
72 return [
73- dict(widgets.read([wid['widget_id'][0]], [], ctx)[0],
74+ dict(widgets.read([wid['widget_id'][0]], ['content', 'id', 'title'], ctx)[0],
75 user_widget_id=wid['id'],
76 # NULL user_id = global = non-removable
77 removable=bool(wid['user_id']))
78
79=== modified file 'addons/openerp/static/javascript/form_state.js'
80--- addons/openerp/static/javascript/form_state.js 2015-09-16 09:02:05 +0000
81+++ addons/openerp/static/javascript/form_state.js 2016-08-26 09:28:44 +0000
82@@ -155,18 +155,19 @@
83 } catch(e){
84 return;
85 }
86+ var cache_values = {};
87
88 for (var attr in attrs) {
89 var expr_fields = {}; // check if field appears more then once in the expr
90
91 if (attrs[attr] == ''){
92- return form_onAttrChange(container, widget, attr, attrs[attr], $this);
93+ return form_onAttrChange(container, widget, attr, attrs[attr], $this, cache_values);
94 }
95
96 forEach(attrs[attr], function(n){
97
98 if (typeof(n) == "number") { // {'invisible': [1]}
99- return form_onAttrChange(container, widget, attr, n, $this);
100+ return form_onAttrChange(container, widget, attr, n, $this, cache_values);
101 }
102
103 var name = prefix + n[0];
104@@ -176,8 +177,8 @@
105 expr_fields[field.id] = 1;
106 // events disconnected during hook_onStateChange,
107 // don't redisconnect or may break onStateChange
108- var $field = jQuery(field).bind('onAttrChange', partial(form_onAttrChange, container, widget, attr, attrs[attr], $this));
109- $field.change(partial(form_onAttrChange, container, widget, attr, attrs[attr], $this));
110+ var $field = jQuery(field).bind('onAttrChange', partial(form_onAttrChange, container, widget, attr, attrs[attr], $this, {}));
111+ $field.change(partial(form_onAttrChange, container, widget, attr, attrs[attr], $this, {}));
112 }
113 });
114 }
115@@ -209,7 +210,11 @@
116 return;
117 }
118
119- var row_is_editable = $this.parents('tr.grid-row').is('.editors')
120+ // check if an editor exists
121+ var editor_exists = $(".editors").length;
122+ var cache_values = {};
123+
124+ var row_is_editable = editor_exists && $this.parents('tr.grid-row').is('.editors');
125 for (var attr in attrs) {
126 if (!row_is_editable && attr != 'invisible') {
127 // when row is not in editable mode we only care about invisible attributes
128@@ -217,30 +222,31 @@
129 continue;
130 }
131 if (attrs[attr] == '') {
132- return form_onAttrChange(container, widget, attr, attrs[attr], $this);
133+ return form_onAttrChange(container, widget, attr, attrs[attr], $this, cache_values);
134 }
135 forEach(attrs[attr], function(n) {
136 if (typeof(n) == "number") { // {'invisible': [1]}
137- return form_onAttrChange(container, widget, attr, n, $this);
138+ return form_onAttrChange(container, widget, attr, n, $this, cache_values);
139 }
140 var name = prefix + n[0];
141 var field = openobject.dom.get(name);
142 if (row_is_editable) {
143- var $field = jQuery(field).bind('onAttrChange', partial(form_onAttrChange, container, widget, attr, attrs[attr], $this));
144- $field.change(partial(form_onAttrChange, container, widget, attr, attrs[attr], $this));
145+ var $field = jQuery(field).bind('onAttrChange', partial(form_onAttrChange, container, widget, attr, attrs[attr], $this, {}));
146+ $field.change(partial(form_onAttrChange, container, widget, attr, attrs[attr], $this, {}));
147 }
148- return form_onAttrChange(container, widget, attr, attrs[attr], $this);
149+ return form_onAttrChange(container, widget, attr, attrs[attr], $this, cache_values);
150 });
151 }
152 });
153 }
154
155-function form_onAttrChange(container, widgetName, attr, expr, elem) {
156+function form_onAttrChange(container, widgetName, attr, expr, elem, cache_values) {
157+ var cache_values = cache_values || {};
158
159 var prefix = widgetName.slice(0, widgetName.lastIndexOf('/') + 1);
160 var widget = openobject.dom.get(widgetName) || elem;
161
162- var result = form_evalExpr(prefix, expr, elem);
163+ var result = form_evalExpr(prefix, expr, elem, cache_values);
164
165 switch (attr) {
166 case 'readonly':
167@@ -260,115 +266,181 @@
168 }
169 }
170
171-function form_find_field_in_context(prefix, field, ref_elem) {
172+function ret_cache_if_available(cache, key, func_eval)
173+{
174+ if(cache[key] == undefined){
175+ val = func_eval()
176+ cache[key] = val;
177+ return val;
178+ }else{
179+ return cache[key];
180+ }
181+}
182+
183+function form_find_field_in_context(prefix, field, ref_elem, cache_values) {
184 // try to find field in the context of reference element (ref_elem)
185 var elem = null;
186- if (ref_elem.parents('table.grid').length) {
187- var parent = ref_elem.parents('tr.grid-row');
188- elem = parent.find(idSelector(prefix + field));
189-
190- if (!elem || !elem.length) {
191- var parent_selector = '[name='+prefix + field +']';
192- elem = parent.find(parent_selector);
193- }
194-
195- if (!elem || !elem.length) {
196- // try getting with _terp_listfields/TABLE_ID/FIELD_NAME
197- var parent_table_id = ref_elem.parents('table.grid')[0].id;
198- if (parent_table_id && parent_table_id.match('_grid$')) {
199- parent_table_id = parent_table_id.slice(0, parent_table_id.length - 5);
200- }
201- if (parent_table_id == '_terp_list') {
202- // in case list name if '_terp_list' this means we're not inside a o2m/m2m fields,
203- // and we no need need to prefix with parent_table_id name
204- parent_table_id = ''
205- } else {
206- parent_table_id = parent_table_id + '/'
207- }
208- var parent_relative_fieldname = '[name=_terp_listfields/' + parent_table_id + prefix + field + ']';
209- elem = parent.find(parent_relative_fieldname);
210- }
211- }
212- if (!elem || !elem.length) {
213- elem = jQuery(idSelector(prefix + field));
214- }
215- return elem;
216+
217+ var key_cache = 'bigcache_' + prefix + '_' + field;
218+
219+ return ret_cache_if_available(cache_values, key_cache, function(){
220+
221+ var parents_grid = ret_cache_if_available(cache_values, 'closest_table.grid', function(){
222+ return ref_elem.closest('table.grid');
223+ });
224+
225+ if (parents_grid.length) {
226+
227+ var parent = ret_cache_if_available(cache_values, 'tr.grid-row', function(){
228+ return ref_elem.closest('tr.grid-row');
229+ });
230+
231+ elem = parent.find(idSelector(prefix + field));
232+
233+ if (!elem || !elem.length) {
234+ var parent_selector = '[name='+prefix + field +']';
235+ elem = parent.find(parent_selector);
236+ }
237+
238+ if (!elem || !elem.length) {
239+ // try getting with _terp_listfields/TABLE_ID/FIELD_NAME
240+ var parent_table_id = parents_grid[0].id;
241+ if (parent_table_id && parent_table_id.match('_grid$')) {
242+ parent_table_id = parent_table_id.slice(0, parent_table_id.length - 5);
243+ }
244+ if (parent_table_id == '_terp_list') {
245+ // in case list name if '_terp_list' this means we're not inside a o2m/m2m fields,
246+ // and we no need need to prefix with parent_table_id name
247+ parent_table_id = ''
248+ } else {
249+ parent_table_id = parent_table_id + '/'
250+ }
251+ var parent_relative_fieldname = '[name=_terp_listfields/' + parent_table_id + prefix + field + ']';
252+ elem = parent.find(parent_relative_fieldname);
253+ }
254+ }
255+ if (!elem || !elem.length) {
256+ elem = jQuery(idSelector(prefix + field));
257+ }
258+ cache_values[key_cache] = elem;
259+ return elem;
260+ });
261 }
262
263-function form_evalExpr(prefix, expr, ref_elem) {
264-
265+
266+function form_evalExpr(prefix, expr, ref_elem, cache_values) {
267+
268+ // the stack contains future that can be evaluated when it's required
269 var stack = [];
270 for (var i = 0; i < expr.length; i++) {
271
272 var ex = expr[i];
273 var op = ex[1];
274- var elem = form_find_field_in_context(prefix, ex[0], ref_elem);
275+
276+ // it's an operator, we don't need to find its value in the page
277 if (ex.length==1) {
278- stack.push(ex[0]);
279+
280+ function val_gen(ret_val){
281+ return function(){
282+ return ret_val;
283+ }
284+ }
285+
286+
287+ stack.push(val_gen(ex[0]));
288 continue;
289 }
290- if (!elem || !elem.length) {
291- continue
292- }
293- var val = ex[2];
294-
295- var elem_value;
296- if(elem.is(':input')) {
297- elem_value = elem.val();
298- } else {
299- elem_value = elem.attr('value') || elem.text();
300- }
301-
302- switch (op.toLowerCase()) {
303- case '=':
304- case '==':
305- stack.push(elem_value == val);
306- break;
307- case '!=':
308- case '<>':
309- stack.push(elem_value != val);
310- break;
311- case '<':
312- stack.push(elem_value < val);
313- break;
314- case '>':
315- stack.push(elem_value > val);
316- break;
317- case '<=':
318- stack.push(elem_value <= val);
319- break;
320- case '>=':
321- stack.push(elem_value >= val);
322- break;
323- case 'in':
324- stack.push(MochiKit.Base.findIdentical(val, elem_value) > -1);
325- break;
326- case 'not in':
327- stack.push(MochiKit.Base.findIdentical(val, elem_value) == -1);
328- break;
329- }
330- }
331- stack = eval_stack(stack, 0);
332-
333- // shouldn't find any `false` left at this point
334- return stack.indexOf(false) == -1;
335+
336+ // create a future in order to evaluate it only if required
337+ function fetch_value(_op, _prefix, ex_0, ex_2, ref_elem){
338+
339+ return function(){
340+ var elem = form_find_field_in_context(_prefix, ex_0, ref_elem, cache_values);
341+
342+ if (!elem || !elem.length) {
343+ return null;
344+ }
345+ var val = ex_2;
346+
347+ var elem_value;
348+ if(elem.is(':input')) {
349+ elem_value = elem.val();
350+ } else {
351+ elem_value = elem.attr('value') || elem.text();
352+ }
353+
354+ switch (_op.toLowerCase()) {
355+ case '=':
356+ case '==':
357+ return elem_value == val;
358+ case '!=':
359+ case '<>':
360+ return elem_value != val;
361+ case '<':
362+ return elem_value < val;
363+ case '>':
364+ return elem_value > val;
365+ case '<=':
366+ return elem_value <= val;
367+ case '>=':
368+ return elem_value >= val;
369+ case 'in':
370+ return MochiKit.Base.findIdentical(val, elem_value) > -1;
371+ case 'not in':
372+ return MochiKit.Base.findIdentical(val, elem_value) == -1;
373+ }
374+
375+ return null;
376+ };
377+ };
378+
379+ stack.push(fetch_value(op, prefix, ex[0], ex[2], ref_elem));
380+ }
381+
382+ ret = true;
383+ position = 0;
384+
385+ while(ret && position < stack.length){
386+ result = eval_stackNew(stack, position, false)
387+
388+ ret = result.value;
389+ position = result.next;
390+ }
391+
392+ return ret;
393 }
394
395-function eval_stack(stack, i) {
396- for (var j=i; j<stack.length; j++) {
397- if (stack[j] == '|') {
398- stack = eval_stack(stack,j+1);
399- stack = eval_stack(stack,j+2);
400- stack.splice(j, 3, stack[j+1] || stack[j+2]);
401- } else if (stack[j] == '&') {
402- stack = eval_stack(stack,j+1);
403- stack = eval_stack(stack,j+2);
404- stack.splice(j, 3, stack[j+1] && stack[j+2]);
405- } else {
406- return stack;
407+function eval_stackNew(stack, i, fuzzy) {
408+
409+ if(stack.length <= i){
410+ return {value: true, next: i+1};
411+ }else{
412+ value = stack[i]()
413+
414+ if(value === null){
415+ return eval_stackNew(stack, i+1, fuzzy);
416+ }else if(value === false || value === true){
417+ return {value: value, next: i+1};
418+ }else if(value === '|'){
419+ var val1 = eval_stackNew(stack, i+1, false)
420+ var val2 = eval_stackNew(stack, val1.next, false)
421+ return {value: val1.value || val2.value, next: val2.next};
422+ }else if(value === '&'){
423+
424+ if(fuzzy){
425+ var val1 = eval_stackNew(stack, i+1, true)
426+ if(!val1.value)
427+ return {value: false, next: undefined};
428+ else
429+ return {value: eval_stackNew(stack, val1.next, true), next: undefined};
430+ }else{
431+ var val1 = eval_stackNew(stack, i+1, false)
432+ var val2 = eval_stackNew(stack, val1.next, false)
433+ return {value: val1.value && val2.value, next: val2.next};
434+ }
435+
436 }
437 }
438- return stack
439 }
440
441 function form_setReadonly(container, fieldName, readonly) {
442
443=== modified file 'addons/openerp/utils/utils.py'
444--- addons/openerp/utils/utils.py 2015-12-02 09:26:54 +0000
445+++ addons/openerp/utils/utils.py 2016-08-26 09:28:44 +0000
446@@ -331,8 +331,8 @@
447
448 value = []
449 for relation_record in relation_objects:
450- id = relation_record.pop('id')
451- value.append(OneToMany.update(id, relation_record))
452+ obj_id = relation_record.pop('id')
453+ value.append(OneToMany.update(obj_id, relation_record))
454 else:
455 value = []
456 except:
457
458=== modified file 'addons/openerp/widgets/form/_action.py'
459--- addons/openerp/widgets/form/_action.py 2011-01-17 11:57:11 +0000
460+++ addons/openerp/widgets/form/_action.py 2016-08-26 09:28:44 +0000
461@@ -46,7 +46,9 @@
462 raise _('Action not found!')
463
464 _type=res[0]['type']
465- self.action = rpc.session.execute('object', 'execute', _type, 'read', [self.act_id], False, rpc.session.context)[0]
466+ self.action = rpc.session.execute('object', 'execute', _type, 'read',
467+ [self.act_id], ['view_mode', 'type', 'domain', 'context',
468+ 'views', 'view_type', 'res_model'], rpc.session.context)[0]
469
470 if 'view_mode' in attrs:
471 self.action['view_mode'] = attrs['view_mode']
472
473=== modified file 'addons/openerp/widgets/form/_form.py'
474--- addons/openerp/widgets/form/_form.py 2016-07-19 15:19:24 +0000
475+++ addons/openerp/widgets/form/_form.py 2016-08-26 09:28:44 +0000
476@@ -517,7 +517,7 @@
477 self.operator = attrs.get('operator', '=')
478 self.search_context = attrs.get('context', {})
479 #Below mentioned process should be followed for m2o as selection and for boolean field on search panel
480- if not self.options and attrs.get('relation') and attrs.get('widget') == 'selection':
481+ if not self.options and attrs.get('relation') and attrs.get('widget') == 'selection' and not attrs.get('get_selection'):
482 proxy = rpc.RPCProxy(attrs['relation'])
483 try:
484 domain = attrs.get('domain', [])
485
486=== modified file 'addons/view_diagram/controllers/process.py'
487--- addons/view_diagram/controllers/process.py 2011-02-17 13:59:18 +0000
488+++ addons/view_diagram/controllers/process.py 2016-08-26 09:28:44 +0000
489@@ -46,7 +46,8 @@
490 help = _('Help: Not Defined')
491 help_ids = rpc.session.execute('object', 'execute', 'ir.actions.act_window', 'search', [('res_model','=',res_model)])
492 for help_id in help_ids:
493- field = rpc.session.execute('object', 'execute', 'ir.actions.act_window', 'read', help_id)
494+ field = rpc.session.execute('object', 'execute',
495+ 'ir.actions.act_window', 'read', help_id, ['help', 'name'])
496 if field['help'] and (field['name'] == title):
497 help = field['help']
498
499
500=== modified file 'openobject/controllers/_root.py'
501--- openobject/controllers/_root.py 2011-05-10 13:22:29 +0000
502+++ openobject/controllers/_root.py 2016-08-26 09:28:44 +0000
503@@ -62,19 +62,6 @@
504 # doesn't restart due to downloading new add-ons or refreshing
505 # existing ones
506 cherrypy.engine.autoreload.unsubscribe()
507- try:
508- obj = pooler.get_pool().get_controller("/openerp/modules")
509- if not obj:
510- raise RuntimeError(
511- "Cannot find controller for /openerp/modules")
512- if obj.has_new_modules():
513- pooler.restart_pool()
514- except AuthenticationError:
515- pass
516-
517- if autoreloader_enabled:
518- # re-enable auto-reloading if it was enabled before
519- cherrypy.engine.autoreload.subscribe()
520
521 request = cherrypy.request
522 self.clean_headers_params(request)

Subscribers

People subscribed via source and target branches