Merge lp:~camptocamp/oerpscenario/trunk-add_load-afe into lp:oerpscenario

Proposed by Alexandre Fayolle - camptocamp
Status: Needs review
Proposed branch: lp:~camptocamp/oerpscenario/trunk-add_load-afe
Merge into: lp:oerpscenario
Diff against target: 111 lines (+107/-0)
1 file modified
features/steps/load.py (+107/-0)
To merge this branch: bzr merge lp:~camptocamp/oerpscenario/trunk-add_load-afe
Reviewer Review Type Date Requested Status
Leonardo Pistone code review Needs Fixing
Review via email: mp+206372@code.launchpad.net

Description of the change

add @given('I load the data file "{filename}.csv" into the model "{model_name}"')
and @given('I load the data file "{filename}.yml"')

the yaml version can process images, which is useful for products.

To post a comment you must log in.
Revision history for this message
Leonardo Pistone (lepistone) wrote :

Thanks!

In fact, we already have a step to import csv files in tools.py, but your one is better, because you check the messages returned by load().

This would have saved me a headache, because load() does not raise on error, so it is important to check the return value.

I suggest you remove the old step in this branch.

review: Needs Fixing (code review)
Revision history for this message
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote :

To port on github

Unmerged revisions

330. By Alexandre Fayolle - camptocamp on 2014-02-14

[ADD] phrases to load csv or yaml files. Yaml files support references to images

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'features/steps/load.py'
2--- features/steps/load.py 1970-01-01 00:00:00 +0000
3+++ features/steps/load.py 2014-02-14 09:50:19 +0000
4@@ -0,0 +1,107 @@
5+import csv
6+import os
7+import base64
8+import yaml
9+from support.tools import set_trace
10+import openerp
11+
12+#---------
13+#from openerp.tools import yaml_import
14+
15+class Image(openerp.tools.yaml_tag.YamlTag):
16+ def __init__(self, path):
17+ self.path = path
18+ super(Image, self).__init__()
19+
20+ def __str__(self):
21+ return '!image %r' % self.path
22+
23+
24+class YamlInterpreter(openerp.tools.YamlInterpreter):
25+ def __init__(self, ctx, *args, **kwargs):
26+ self.ctx=ctx
27+ return super(YamlInterpreter,self).__init__(*args,**kwargs)
28+
29+ def process(self, yaml_string):
30+ def image_constructor(loader, node):
31+ expression = loader.construct_scalar(node)
32+ return Image(expression)
33+ yaml.add_constructor(u"!image", image_constructor)
34+ return super(YamlInterpreter,self).process(yaml_string)
35+
36+ def process_image(self, node):
37+ return base64.encodestring(_fileopen(self.ctx, node.path).read())
38+
39+ def _eval_field(self, cmodel, field_name, expression, view_info=False, parent=None, default=True):
40+ # Allow to ref m2o with search criteria
41+ # TODO : push as MP on server
42+ if parent is None:
43+ parent={}
44+ if field_name in cmodel._columns:
45+ column = cmodel._columns[field_name]
46+ elif field_name in cmodel._inherit_fields:
47+ column = cmodel._inherit_fields[field_name][2]
48+ else:
49+ raise KeyError("Object '%s' does not contain field '%s'" % (cmodel, field_name))
50+ if column._type == "many2one":
51+ if isinstance(expression,dict):
52+ domain=[(k,'=',v) for k,v in expression.iteritems()]
53+ return model(column._obj).search(domain)
54+ elif isinstance(expression,Image):
55+ return self.process_image(expression)
56+ return super(YamlInterpreter,self)._eval_field(cmodel, field_name, expression, view_info=view_info, parent=parent, default=default)
57+
58+
59+def yaml_import(ctx, cr, module_name, fp, kind, mode='init'):
60+ idref = {}
61+ yaml_interpreter = YamlInterpreter(ctx, cr, module_name, idref, mode='update', filename=fp.name)
62+ yaml_interpreter.process(fp.read())
63+
64+
65+def _fileopen(ctx, filename, mode='r'):
66+ tmp_path = ctx.feature.filename.split(os.path.sep)
67+ tmp_path = tmp_path[1: tmp_path.index('features')] + ['data', '%s'%filename]
68+ tmp_path = [str(x) for x in tmp_path]
69+ path = os.path.join('/', *tmp_path)
70+ assert os.path.exists(path)
71+ return open(path, mode)
72+
73+
74+@given('I load the data file "{filename}.csv" into the model "{model_name}"')
75+def impl(ctx, model_name, filename, sep=","):
76+ data = csv.reader(_fileopen(ctx, '%s.csv'%filename, 'rb'), delimiter=str(sep))
77+ head = []
78+ skip = [] #skip columns that are not mapped
79+ for index,field in enumerate(data.next()):
80+ if field:
81+ head.append(field)
82+ else:
83+ skip.append(index)
84+ values=[]
85+ for line in data:
86+ values.append([field for index,field in enumerate(line) if index not in skip])
87+ rewrite=[i for i,e in enumerate(head) if e=='id' or e.endswith('/id')]
88+ if rewrite:
89+ for line in iter(values):
90+ for pos in rewrite:
91+ if line[pos] and '.' not in line[pos]:
92+ line[pos]='scenario.'+line[pos]
93+ result = model(model_name).load(head, values)
94+ has_errors = any(m for m in result['messages'] if m['type'] == 'error')
95+ assert not has_errors, result
96+
97+
98+
99+@given('I load the data file "{filename}.yml"')
100+def impl(ctx, filename):
101+ openerp = ctx.conf['server']
102+ db_name = ctx.conf['db_name']
103+ pool = openerp.modules.registry.RegistryManager.get(db_name)
104+ cr = pool.db.cursor()
105+ module_name='scenario'
106+ fp=_fileopen(ctx, '%s.yml'%filename)
107+ try:
108+ cr.autocommit(True)
109+ yaml_import(ctx, cr, module_name, fp, 'data', mode='update')
110+ finally:
111+ cr.close()

Subscribers

People subscribed via source and target branches

to all changes: