Merge lp:~openerp-dev/openobject-client-web/export into lp:openobject-client-web/trunk

Proposed by Kunal Chavda
Status: Merged
Merged at revision: 3948
Proposed branch: lp:~openerp-dev/openobject-client-web/export
Merge into: lp:openobject-client-web/trunk
Diff against target: 274 lines (+52/-52)
2 files modified
addons/openerp/controllers/impex.py (+25/-20)
addons/openerp/controllers/templates/exp.mako (+27/-32)
To merge this branch: bzr merge lp:~openerp-dev/openobject-client-web/export
Reviewer Review Type Date Requested Status
Navrang Oza (community) Approve
Xavier (Open ERP) (community) Needs Fixing
Review via email: mp+41588@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Xavier (Open ERP) (xmo-deactivatedaccount) wrote :

0. Please perform reformattings (even automated by your IDE) in different revisions than you perform actual work, mixing them makes reviews and reading history harder than it should (you are not limited in the number of revisions you use, so don't worry about that)

1. If we have only one value (namely CSV), there is no need to display the control/section at all since there is no choice and csv is the default output format. Thus instead of a sequence of export format you could just as well use a boolean `enable_excel_export` (or something like that) flag and only display the control if it's `True` (as far as I know, we're not expected to add new export formats anytime soon). That flag would simply be set if we can import xlwt, unset otherwise

2. This means you can also move the xlwt import to the toplevel of the module (instead of within functions) wrapped in an except

3. Please use precise as exception catch as you can: the error we're looking for here is specifically ImportError, we don't want to "eat" exceptions due to e.g. a broken xlwt installation

review: Needs Fixing
Revision history for this message
Navrang Oza (noz-tiny) wrote :

> 0. Please perform reformattings (even automated by your IDE) in different
> revisions than you perform actual work, mixing them makes reviews and reading
> history harder than it should (you are not limited in the number of revisions
> you use, so don't worry about that)
>
> 1. If we have only one value (namely CSV), there is no need to display the
> control/section at all since there is no choice and csv is the default output
> format. Thus instead of a sequence of export format you could just as well use
> a boolean `enable_excel_export` (or something like that) flag and only display
> the control if it's `True` (as far as I know, we're not expected to add new
> export formats anytime soon). That flag would simply be set if we can import
> xlwt, unset otherwise

Conclusion what I understood: If xlwt is not installed then only CSV option will be there and as boolean option "Excel" option will be available. When user will click for Excel then error message will raise "Please Install xlwt Library ......". RIGHT ??

> 2. This means you can also move the xlwt import to the toplevel of the module
> (instead of within functions) wrapped in an except

If we import xlwt to the top level, then how will we check that it is installed or not ?
How can we raise error ?
We have to keep in try/catch somewhere.

> 3. Please use precise as exception catch as you can: the error we're looking
> for here is specifically ImportError, we don't want to "eat" exceptions due to
> e.g. a broken xlwt installation

Revision history for this message
Xavier (Open ERP) (xmo-deactivatedaccount) wrote :

> Conclusion what I understood: If xlwt is not installed then only CSV option will be there and as boolean option "Excel" option will be available. When user will click for Excel then error message will raise "Please Install xlwt Library ......". RIGHT ??

I don't think so, I'd rather have no option at all if only CSV export is available, an option for which you can't make any choice is useless cognitive burden for the user.

I will ask Aline about it though, just to be sure.

> If we import xlwt to the top level, then how will we check that it is installed or not ?

try:
    import xlwt
    xls_export_available = True
except ImportError:
    xls_export_available = False

> How can we raise error ?
We don't raise error, that's the point.

> We have to keep in try/catch somewhere.
Sure, but that can be at the toplevel.

Revision history for this message
Navrang Oza (noz-tiny) wrote :

> > Conclusion what I understood: If xlwt is not installed then only CSV option
> will be there and as boolean option "Excel" option will be available. When
> user will click for Excel then error message will raise "Please Install xlwt
> Library ......". RIGHT ??
>
> I don't think so, I'd rather have no option at all if only CSV export is
> available, an option for which you can't make any choice is useless cognitive
> burden for the user.

That is also true. Actually in GTK there is not Excel option available.

>
> I will ask Aline about it though, just to be sure.
>
> > If we import xlwt to the top level, then how will we check that it is
> installed or not ?
>
> try:
> import xlwt
> xls_export_available = True
> except ImportError:
> xls_export_available = False
>
> > How can we raise error ?
> We don't raise error, that's the point.
>
> > We have to keep in try/catch somewhere.
> Sure, but that can be at the toplevel.

3931. By Kunal Chavda

[IMP] Improved code.

Revision history for this message
Xavier (Open ERP) (xmo-deactivatedaccount) wrote :

There is no need for the following code:

    % else:
        <td>
            <input type="radio" id="export_as" name="export_as" value="csv" checked/>
        </td>
        <td>
            ${_("Export as CSV")}
        </td>

If Excel export is not available, csv is default export format, so clicking export will generate a CSV export.

Also, as I asked noz (i think, though I may have forgotten), please merge the two options fieldsets, aline finds there is no need for two different ones for the same things.

review: Needs Fixing
3932. By Kunal Chavda

[IMP] Improved Code.

Revision history for this message
Kunal Chavda (kunal-chavda) wrote :

Hello Sir,

As per your suggestion I have fixed changes.

Thanks.

Revision history for this message
Navrang Oza (noz-tiny) wrote :

I have checked, and its working fine.
You can merge it.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'addons/openerp/controllers/impex.py'
2--- addons/openerp/controllers/impex.py 2010-11-09 09:24:23 +0000
3+++ addons/openerp/controllers/impex.py 2010-11-25 06:20:12 +0000
4@@ -39,6 +39,13 @@
5 from openobject.tools import expose, redirect, ast
6
7
8+try:
9+ import xlwt
10+ xls_export_available = True
11+except:
12+ xls_export_available = False
13+
14+
15 def datas_read(ids, model, fields, context=None):
16 ctx = dict((context or {}), **rpc.session.context)
17 return rpc.RPCProxy(model).export_data(ids, fields, ctx)
18@@ -71,7 +78,7 @@
19 raise common.message(_("Operation failed\nI/O error")+"(%s)" % (errno,))
20
21 def _fields_get_all(model, views, context=None):
22-
23+
24 context = context or {}
25
26 def parse(root, fields):
27@@ -117,7 +124,7 @@
28 @expose(template="/openerp/controllers/templates/exp.mako")
29 def exp(self, **kw):
30 params, data = TinyDict.split(kw)
31-
32+
33 ctx = dict((params.context or {}), **rpc.session.context)
34
35 views = {}
36@@ -143,11 +150,12 @@
37 new_list = listgrid.List(name='_terp_list', model='ir.exports', view=view, ids=None,
38 domain=[('resource', '=', params.model)],
39 context=ctx, selectable=1, editable=False, pageable=False, impex=True)
40-
41+
42+
43
44 return dict(new_list=new_list, model=params.model, ids=params.ids, ctx=ctx,
45 search_domain=params.search_domain, source=params.source,
46- tree=tree)
47+ tree=tree, xls_export_available=xls_export_available)
48
49 @expose()
50 def save_exp(self, **kw):
51@@ -178,23 +186,23 @@
52 @expose('json')
53 def get_fields(self, model, prefix='', name='', field_parent=None, **kw):
54
55- is_importing = kw.get('is_importing', False)
56-
57+ is_importing = kw.get('is_importing', False)
58+
59 try:
60 ctx = ast.literal_eval(kw['context'])
61 except:
62 ctx = {}
63-
64+
65 ctx.update(**rpc.session.context)
66
67 try:
68 views = ast.literal_eval(kw['views'])
69 except:
70 views = {}
71-
72+
73
74 fields = _fields_get_all(model, views, ctx)
75-
76+
77 fields.update({'id': {'string': 'ID'}, 'db_id': {'string': 'Database ID'}})
78
79 fields_order = fields.keys()
80@@ -257,7 +265,7 @@
81 def get_namelist(self, **kw):
82
83 params, data = TinyDict.split(kw)
84-
85+
86 ctx = dict((params.context or {}), **rpc.session.context)
87
88 id = params.id
89@@ -343,11 +351,8 @@
90 params.fields2 = fields
91
92 if export_as == 'xls':
93- try:
94- import xlwt
95- except ImportError:
96- raise common.warning(_('Please Install xlwt Library.\nTo create spreadsheet files compatible with MS Excel.'), _('Import Error.'))
97
98+ import xlwt
99 ezxf = xlwt.easyxf
100
101 fp = StringIO.StringIO()
102@@ -380,9 +385,9 @@
103 @expose(template="/openerp/controllers/templates/imp.mako")
104 def imp(self, **kw):
105 params, data = TinyDict.split(kw)
106-
107+
108 ctx = dict((params.context or {}), **rpc.session.context)
109-
110+
111 views = {}
112 if params.view_mode and params.view_ids:
113 for i, view in enumerate(params.view_mode):
114@@ -408,11 +413,11 @@
115
116 _fields = {}
117 _fields_invert = {}
118-
119+
120 fields = dict(rpc.RPCProxy(params.model).fields_get(False, rpc.session.context),
121 id={'type': 'char', 'string': 'ID'},
122 db_id={'type': 'char', 'string': 'Database ID'})
123-
124+
125 def model_populate(fields, prefix_node='', prefix=None, prefix_value='', level=2):
126 def str_comp(x,y):
127 if x<y: return 1
128@@ -426,7 +431,7 @@
129 and (not fields[field].get('readonly')\
130 or not dict(fields[field].get('states', {}).get(
131 'draft', [('readonly', True)])).get('readonly',True)):
132-
133+
134 st_name = prefix_value+fields[field]['string'] or field
135 _fields[prefix_node+field] = st_name
136 _fields_invert[st_name] = prefix_node+field
137@@ -474,7 +479,7 @@
138 data = list(csv.reader(input, quotechar=str(csvdel), delimiter=str(csvsep)))[int(csvskip):]
139 datas = []
140 ctx = dict(rpc.session.context)
141-
142+
143 if not isinstance(fields, list):
144 fields = [fields]
145
146
147=== modified file 'addons/openerp/controllers/templates/exp.mako'
148--- addons/openerp/controllers/templates/exp.mako 2010-11-09 09:04:31 +0000
149+++ addons/openerp/controllers/templates/exp.mako 2010-11-25 06:20:12 +0000
150@@ -7,9 +7,9 @@
151
152 <script type="text/javascript">
153 function add_fields(){
154-
155+
156 var tree = treeGrids['${tree.name}'];
157-
158+
159 var fields = tree.selection;
160 var select = openobject.dom.get('fields');
161
162@@ -28,7 +28,7 @@
163 select.options.add(new Option(text, id));
164 });
165 }
166-
167+
168 function open_savelist(id) {
169 var elem = openobject.dom.get(id);
170 elem.style.display = elem.style.display == 'none' ? '' : 'none';
171@@ -56,7 +56,7 @@
172 });
173 }
174 }
175-
176+
177 function do_select(id, src) {
178 openobject.dom.get('fields').innerHTML = '';
179 var model = openobject.dom.get('_terp_model').value;
180@@ -87,7 +87,7 @@
181 var id = boxes[0].value;
182 form.action = openobject.http.getURL('/openerp/impex/delete_listname', {'_terp_id' : id});
183 form.submit();
184-
185+
186 }
187
188 function reload(name_list) {
189@@ -148,7 +148,7 @@
190 </tr>
191 </table>
192 </td>
193- </tr>
194+ </tr>
195 % if new_list.ids:
196 <tr>
197 <td class="side_spacing">
198@@ -211,13 +211,13 @@
199 </td>
200 </tr>
201 <tr>
202- <td class="side_spacing">
203+ <td class="side_spacing">
204 <div id="savelist" style="display: none">
205 <fieldset>
206 <legend>${_("Save List")}</legend>
207 <table>
208- <tr>
209- <td class="label">${_("Name of This Export:")}</td>
210+ <tr>
211+ <td class="label">${_("Name of This Export:")}</td>
212 <td>
213 <input type="text" id="savelist_name" name="savelist_name"/>
214 </td>
215@@ -226,41 +226,36 @@
216 </td>
217 </tr>
218 </table>
219- </fieldset>
220- </div>
221+ </fieldset>
222+ </div>
223 </td>
224- </tr>
225+ </tr>
226 <tr>
227- <td class="side_spacing">
228- <fieldset>
229- <legend>${_("Options")}</legend>
230+ <td class="side_spacing">
231+ <fieldset title="Restricts the number of exportable fields to ensure you will be able to import your data back in OpenERP">
232+ <legend>${_("Select Options to Export")}</legend>
233 <table>
234- <tr>
235- <td>
236- <select id="export_as" name="export_as">
237+ <tr>
238+ % if xls_export_available == True:
239+ <td style="padding-right: 8px;">
240+ <select style="height:18px" id="export_as" name="export_as">
241 <option value="csv">${_("Export as CSV")}</option>
242 <option value="xls">${_("Export as Excel")}</option>
243 </select>
244 </td>
245+ % else:
246+ <td>
247+ <input type="hidden" id="export_as" name="export_as" value="csv"/>
248+ </td>
249+ % endif
250 <td>
251 <input type="checkbox" class="checkbox" name="add_names" checked="checked"/>
252 </td>
253- <td>${_("Add field names")}</td>
254- </tr>
255- </table>
256- </fieldset>
257- </td>
258- </tr>
259- <tr>
260- <td class="side_spacing">
261- <fieldset title="Restricts the number of exportable fields to ensure you will be able to import your data back in OpenERP">
262- <legend>${_("Select an Option to Export")}</legend>
263- <table>
264- <tr>
265- <td>
266+ <td style="padding-left:3px">${_("Add field names")}</td>
267+ <td style="padding-left:8px">
268 <input type="checkbox" class="checkbox" name="import_compat" id="import_compat"/>
269 </td>
270- <td><label for="import_compat"
271+ <td style="padding-left:3px"><label for="import_compat"
272 >${_("Import Compatible")}</label></td>
273 </tr>
274 </table>