Merge lp:~openerp-dev/openobject-server/trunk-methport-thu into lp:openobject-server

Proposed by Vo Minh Thu
Status: Merged
Merged at revision: 4839
Proposed branch: lp:~openerp-dev/openobject-server/trunk-methport-thu
Merge into: lp:openobject-server
Diff against target: 552 lines (+172/-53)
20 files modified
doc/03_module_dev.rst (+1/-0)
doc/changelog.rst (+3/-0)
doc/report-declaration.rst (+23/-0)
openerp/addons/base/ir/ir_actions.py (+40/-18)
openerp/addons/base/ir/ir_actions.xml (+1/-0)
openerp/conf/deprecation.py (+18/-0)
openerp/import_xml.rng (+1/-0)
openerp/modules/graph.py (+0/-2)
openerp/modules/migration.py (+0/-2)
openerp/modules/registry.py (+0/-1)
openerp/netsvc.py (+21/-5)
openerp/osv/orm.py (+9/-0)
openerp/report/__init__.py (+9/-0)
openerp/report/interface.py (+13/-7)
openerp/report/print_xml.py (+1/-1)
openerp/report/report_sxw.py (+13/-2)
openerp/service/report.py (+3/-5)
openerp/tools/convert.py (+2/-3)
openerp/tools/test_reports.py (+5/-5)
openerp/tools/yaml_import.py (+9/-2)
To merge this branch: bzr merge lp:~openerp-dev/openobject-server/trunk-methport-thu
Reviewer Review Type Date Requested Status
OpenERP Core Team Pending
Review via email: mp+149591@code.launchpad.net

Description of the change

- [X] Write doc.
- [X] Write changelog.
- [ ] Deprecate report registration with Python. I can't really do it: some reports are instanciated before nestv.init_loggers() is called. I could add a simple print statement instead.

Some old-style records are declared by instanciating a custom sub-class of report_rml. It the capability needed to register third-party reports ? If so, an additional attribute can be used to specify the class to instanciate.

To post a comment you must log in.
Revision history for this message
Vo Minh Thu (thu) wrote :

This will make report registration more uniform, and report rendering be possible through the ORM (and thus the model service, instead of the report service).

To register a report, always use the database, i.e. a <report> tag within an XML file. The custom parser, if any, will be specified in the database. Previously specify a custom parser, the report was declared in Python.

Each model will expose a render_report() method, which will take the report name (as many report can be defined on a single model) in argument.

4813. By Vo Minh Thu

[IMP] netsvc: slightly more explicit warning when using LocalService().

4814. By Vo Minh Thu

[MERGE] merged trunk.

4815. By Vo Minh Thu

[REF] ir.actions.report.xml: register_all do not make sense any more:

auto=True reports are looked up in the database for each rendering, so they do
no have to be in the report registry any longer.
auto=False reports will register themselves but at this point
they can be updated to use the new `parser` XML attribute.

4816. By Vo Minh Thu

[REF] ir.actions.report.xml: renamed ids to res_ids because those are not the self model IDs.

4817. By Vo Minh Thu

[FIX] reports: now that _register_all() has been removed, LocalService() must be modified to do the lookup in the database too.

4818. By Vo Minh Thu

[IMP] netsvc: LocalService deprecation now guarded via openerp.conf.deprecation.

4819. By Vo Minh Thu

[IMP] report: registration deprecation now guarded via openerp.conf.deprecation.

4820. By Vo Minh Thu

[IMP] conf.deprecation: comment.

4821. By Vo Minh Thu

[IMP] orm: added a print_report() method.

4822. By Vo Minh Thu

[DOC] changelog updated to mention the new print_report().

4823. By Vo Minh Thu

[IMP] yaml_import: add openerp in the evaluation context.

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

* Imports in functions? I guess the openerp imports are because of recursive blowups, but why do os or operator need to be in functions and not at the module toplevel (openerp/addons/base/ir/ir_actions._lookup_report). Also rather than import openerp why not import openerp.report or openerp.report.interface and not risk recursive import issues?

* the conditional nesting in that function is odd as well, why not:

    if 'report.' + name in openerp.report.interface.report_int._reports:
        return openerp.report.interface.report_int._reports['report.' + name]

    cr.execute("SELECT * FROM ir_act_report_xml WHERE report_name=%s", (name,))
    r = cr.dictfetchone()
    if not r:
        raise Exception, "Required report does not exist: %s" % r

    if r['report_rml'] or r['report_rml_content_data']:
        if r['parser']:
            kwargs = { 'parser': operator.attrgetter(r['parser'])(openerp.addons) }
        else:
            kwargs = {}
        return report_sxw('report.'+r['report_name'], r['model'],
                opj('addons',r['report_rml'] or '/'), header=r['header'], register=False, **kwargs)
    elif r['report_xsl']:
        return report_rml('report.'+r['report_name'], r['model'],
                opj('addons',r['report_xml']),
                r['report_xsl'] and opj('addons',r['report_xsl']), register=False)

    raise Exception, "Unhandled report type: %s" % r

* typo in LocalService docstring (fucntion)

* openerp/tools/convert.py, why not add (parser, parser) to the attribute iteration at line 292?

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

also, in yaml_import `code_context.update({'self': model})` could probably be merged into the dict literal

4824. By Vo Minh Thu

[REF] yaml_import: removed nested import openerp.

4825. By Vo Minh Thu

[REF] removed nested import openerp.

4826. By Vo Minh Thu

[DOC] netsvc: typo in docstring.

4827. By Vo Minh Thu

[REF] trolls.convert: missed an opportunity to reuse a beautiful association list.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'doc/03_module_dev.rst'
2--- doc/03_module_dev.rst 2012-11-19 14:39:12 +0000
3+++ doc/03_module_dev.rst 2013-03-27 15:55:25 +0000
4@@ -13,3 +13,4 @@
5 03_module_dev_04
6 03_module_dev_05
7 03_module_dev_06
8+ report-declaration
9
10=== modified file 'doc/changelog.rst'
11--- doc/changelog.rst 2013-02-21 12:18:25 +0000
12+++ doc/changelog.rst 2013-03-27 15:55:25 +0000
13@@ -6,6 +6,9 @@
14 `trunk`
15 -------
16
17+- Almost removed ``LocalService()``. For reports,
18+ ``openerp.osv.orm.Model.print_report()`` can be used. For workflows, see
19+ :ref:`orm-workflows`.
20 - Removed support for the ``NET-RPC`` protocol.
21 - Added the :ref:`Long polling <longpolling-worker>` worker type.
22 - Added :ref:`orm-workflows` to the ORM.
23
24=== added file 'doc/report-declaration.rst'
25--- doc/report-declaration.rst 1970-01-01 00:00:00 +0000
26+++ doc/report-declaration.rst 2013-03-27 15:55:25 +0000
27@@ -0,0 +1,23 @@
28+.. _report-declaration:
29+
30+Report declaration
31+==================
32+
33+.. versionadded:: 7.1
34+
35+Before version 7.1, report declaration could be done in two different ways:
36+either via a ``<report>`` tag in XML, or via such a tag and a class
37+instanciation in a Python module. Instanciating a class in a Python module was
38+necessary when a custom parser was used.
39+
40+In version 7.1, the recommended way to register a report is to use only the
41+``<report>`` XML tag. The tag can now support an additional ``parser``
42+attribute. The value for that attibute must be a fully-qualified class name,
43+without the leading ``openerp.addons.`` namespace.
44+
45+.. note::
46+ The rational to deprecate the manual class instanciation is to make all
47+ reports visible in the database, have a unique way to declare reports
48+ instead of two, and remove the need to maintain a registry of reports in
49+ memory.
50+
51
52=== modified file 'openerp/addons/base/ir/ir_actions.py'
53--- openerp/addons/base/ir/ir_actions.py 2013-03-19 14:27:01 +0000
54+++ openerp/addons/base/ir/ir_actions.py 2013-03-27 15:55:25 +0000
55@@ -20,11 +20,13 @@
56 ##############################################################################
57
58 import logging
59+import operator
60 import os
61 import re
62 from socket import gethostname
63 import time
64
65+import openerp
66 from openerp import SUPERUSER_ID
67 from openerp import netsvc, tools
68 from openerp.osv import fields, osv
69@@ -85,26 +87,45 @@
70 res[report.id] = False
71 return res
72
73- def register_all(self, cr):
74- """Report registration handler that may be overridden by subclasses to
75- add their own kinds of report services.
76- Loads all reports with no manual loaders (auto==True) and
77- registers the appropriate services to implement them.
78+ def _lookup_report(self, cr, name):
79+ """
80+ Look up a report definition.
81 """
82 opj = os.path.join
83- cr.execute("SELECT * FROM ir_act_report_xml WHERE auto=%s ORDER BY id", (True,))
84- result = cr.dictfetchall()
85- reports = openerp.report.interface.report_int._reports
86- for r in result:
87- if reports.has_key('report.'+r['report_name']):
88- continue
89- if r['report_rml'] or r['report_rml_content_data']:
90- report_sxw('report.'+r['report_name'], r['model'],
91- opj('addons',r['report_rml'] or '/'), header=r['header'])
92- if r['report_xsl']:
93- report_rml('report.'+r['report_name'], r['model'],
94- opj('addons',r['report_xml']),
95- r['report_xsl'] and opj('addons',r['report_xsl']))
96+
97+ # First lookup in the deprecated place, because if the report definition
98+ # has not been updated, it is more likely the correct definition is there.
99+ # Only reports with custom parser sepcified in Python are still there.
100+ if 'report.' + name in openerp.report.interface.report_int._reports:
101+ new_report = openerp.report.interface.report_int._reports['report.' + name]
102+ else:
103+ cr.execute("SELECT * FROM ir_act_report_xml WHERE report_name=%s", (name,))
104+ r = cr.dictfetchone()
105+ if r:
106+ if r['report_rml'] or r['report_rml_content_data']:
107+ if r['parser']:
108+ kwargs = { 'parser': operator.attrgetter(r['parser'])(openerp.addons) }
109+ else:
110+ kwargs = {}
111+ new_report = report_sxw('report.'+r['report_name'], r['model'],
112+ opj('addons',r['report_rml'] or '/'), header=r['header'], register=False, **kwargs)
113+ elif r['report_xsl']:
114+ new_report = report_rml('report.'+r['report_name'], r['model'],
115+ opj('addons',r['report_xml']),
116+ r['report_xsl'] and opj('addons',r['report_xsl']), register=False)
117+ else:
118+ raise Exception, "Unhandled report type: %s" % r
119+ else:
120+ raise Exception, "Required report does not exist: %s" % r
121+
122+ return new_report
123+
124+ def render_report(self, cr, uid, res_ids, name, data, context=None):
125+ """
126+ Look up a report definition and render the report for the provided IDs.
127+ """
128+ new_report = self._lookup_report(cr, name)
129+ return new_report.create(cr, uid, res_ids, data, context)
130
131 _name = 'ir.actions.report.xml'
132 _inherit = 'ir.actions.actions'
133@@ -140,6 +161,7 @@
134 'report_sxw_content': fields.function(_report_content, fnct_inv=_report_content_inv, type='binary', string='SXW Content',),
135 'report_rml_content': fields.function(_report_content, fnct_inv=_report_content_inv, type='binary', string='RML Content'),
136
137+ 'parser': fields.char('Parser Class'),
138 }
139 _defaults = {
140 'type': 'ir.actions.report.xml',
141
142=== modified file 'openerp/addons/base/ir/ir_actions.xml'
143--- openerp/addons/base/ir/ir_actions.xml 2012-12-05 16:00:15 +0000
144+++ openerp/addons/base/ir/ir_actions.xml 2013-03-27 15:55:25 +0000
145@@ -82,6 +82,7 @@
146 <group string="Miscellaneous">
147 <field name="multi"/>
148 <field name="auto"/>
149+ <field name="parser"/>
150 </group>
151 </group>
152 </page>
153
154=== modified file 'openerp/conf/deprecation.py'
155--- openerp/conf/deprecation.py 2013-02-09 06:02:46 +0000
156+++ openerp/conf/deprecation.py 2013-03-27 15:55:25 +0000
157@@ -26,6 +26,8 @@
158 track of those specific measures by providing variables that can be unset
159 by the user to check if her code is future proof.
160
161+In a perfect world, all these variables are set to False, the corresponding
162+code removed, and thus these variables made unnecessary.
163 """
164
165 # If True, the Python modules inside the openerp namespace are made available
166@@ -35,4 +37,20 @@
167 # Change to False around 2013.02.
168 open_openerp_namespace = False
169
170+# If True, openerp.netsvc.LocalService() can be used to lookup reports or to
171+# access openerp.workflow.
172+# Introduced around 2013.03.
173+# Among the related code:
174+# - The openerp.netsvc.LocalService() function.
175+# - The openerp.report.interface.report_int._reports dictionary.
176+# - The register attribute in openerp.report.interface.report_int (and in its
177+# - auto column in ir.actions.report.xml.
178+# inheriting classes).
179+allow_local_service = True
180+
181+# Applies for the register attribute in openerp.report.interface.report_int.
182+# See comments for allow_local_service above.
183+# Introduced around 2013.03.
184+allow_report_int_registration = True
185+
186 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
187
188=== modified file 'openerp/import_xml.rng'
189--- openerp/import_xml.rng 2013-02-12 15:23:28 +0000
190+++ openerp/import_xml.rng 2013-03-27 15:55:25 +0000
191@@ -107,6 +107,7 @@
192 <rng:optional><rng:attribute name="sxw"/></rng:optional>
193 <rng:optional><rng:attribute name="xml"/></rng:optional>
194 <rng:optional><rng:attribute name="xsl"/></rng:optional>
195+ <rng:optional><rng:attribute name="parser"/></rng:optional>
196 <rng:optional> <rng:attribute name="auto" /> </rng:optional>
197 <rng:optional> <rng:attribute name="header" /> </rng:optional>
198 <rng:optional> <rng:attribute name="webkit_header" /> </rng:optional>
199
200=== modified file 'openerp/modules/graph.py'
201--- openerp/modules/graph.py 2012-11-29 14:07:45 +0000
202+++ openerp/modules/graph.py 2013-03-27 15:55:25 +0000
203@@ -36,8 +36,6 @@
204 import openerp.pooler as pooler
205 from openerp.tools.translate import _
206
207-import openerp.netsvc as netsvc
208-
209 import zipfile
210 import openerp.release as release
211
212
213=== modified file 'openerp/modules/migration.py'
214--- openerp/modules/migration.py 2012-01-24 12:42:52 +0000
215+++ openerp/modules/migration.py 2013-03-27 15:55:25 +0000
216@@ -36,8 +36,6 @@
217 import openerp.pooler as pooler
218 from openerp.tools.translate import _
219
220-import openerp.netsvc as netsvc
221-
222 import zipfile
223 import openerp.release as release
224
225
226=== modified file 'openerp/modules/registry.py'
227--- openerp/modules/registry.py 2013-02-12 08:53:11 +0000
228+++ openerp/modules/registry.py 2013-03-27 15:55:25 +0000
229@@ -225,7 +225,6 @@
230 try:
231 Registry.setup_multi_process_signaling(cr)
232 registry.do_parent_store(cr)
233- registry.get('ir.actions.report.xml').register_all(cr)
234 cr.commit()
235 finally:
236 cr.close()
237
238=== modified file 'openerp/netsvc.py'
239--- openerp/netsvc.py 2013-03-19 16:37:08 +0000
240+++ openerp/netsvc.py 2013-03-27 15:55:25 +0000
241@@ -21,11 +21,9 @@
242 ##############################################################################
243
244
245-import errno
246 import logging
247 import logging.handlers
248 import os
249-import platform
250 import release
251 import sys
252 import threading
253@@ -46,12 +44,30 @@
254 _logger = logging.getLogger(__name__)
255
256 def LocalService(name):
257- # Special case for addons support, will be removed in a few days when addons
258- # are updated to directly use openerp.osv.osv.service.
259+ """
260+ The openerp.netsvc.LocalService() function is deprecated. It still works
261+ in two cases: workflows and reports. For workflows, instead of using
262+ LocalService('workflow'), openerp.workflow should be used (better yet,
263+ methods on openerp.osv.orm.Model should be used). For reports,
264+ openerp.report.render_report() should be used (methods on the Model should
265+ be provided too in the future).
266+ """
267+ assert openerp.conf.deprecation.allow_local_service
268+ _logger.warning("LocalService() is deprecated since march 2013 (it was called with '%s')." % name)
269+
270 if name == 'workflow':
271 return openerp.workflow
272
273- return openerp.report.interface.report_int._reports[name]
274+ if name.startswith('report.'):
275+ report = openerp.report.interface.report_int._reports.get(name)
276+ if report:
277+ return report
278+ else:
279+ dbname = getattr(threading.currentThread(), 'dbname', None)
280+ if dbname:
281+ registry = openerp.modules.registry.RegistryManager.get(dbname)
282+ with registry.cursor() as cr:
283+ return registry['ir.actions.report.xml']._lookup_report(cr, name[len('report.'):])
284
285 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, _NOTHING, DEFAULT = range(10)
286 #The background is set with 40 plus the number of the color, and the foreground with 30
287
288=== modified file 'openerp/osv/orm.py'
289--- openerp/osv/orm.py 2013-03-21 13:32:02 +0000
290+++ openerp/osv/orm.py 2013-03-27 15:55:25 +0000
291@@ -5155,6 +5155,15 @@
292 get_xml_id = get_external_id
293 _get_xml_ids = _get_external_ids
294
295+ def print_report(self, cr, uid, ids, name, data, context=None):
296+ """
297+ Render the report `name` for the given IDs. The report must be defined
298+ for this model, not another.
299+ """
300+ report = self.pool['ir.actions.report.xml']._lookup_report(cr, name)
301+ assert self._name == report.table
302+ return report.create(cr, uid, ids, data, context)
303+
304 # Transience
305 def is_transient(self):
306 """ Return whether the model is transient.
307
308=== modified file 'openerp/report/__init__.py'
309--- openerp/report/__init__.py 2013-02-12 14:24:10 +0000
310+++ openerp/report/__init__.py 2013-03-27 15:55:25 +0000
311@@ -19,6 +19,8 @@
312 #
313 ##############################################################################
314
315+import openerp
316+
317 import interface
318 import print_xml
319 import print_fnc
320@@ -30,6 +32,13 @@
321
322 import printscreen
323
324+def render_report(cr, uid, ids, name, data, context=None):
325+ """
326+ Helper to call ``ir.actions.report.xml.render_report()``.
327+ """
328+ registry = openerp.modules.registry.RegistryManager.get(cr.dbname)
329+ return registry['ir.actions.report.xml'].render_report(cr, uid, ids, name, data, context)
330+
331
332 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
333
334
335=== modified file 'openerp/report/interface.py'
336--- openerp/report/interface.py 2013-02-01 11:22:32 +0000
337+++ openerp/report/interface.py 2013-03-27 15:55:25 +0000
338@@ -25,6 +25,7 @@
339 from lxml import etree
340 import openerp.pooler as pooler
341
342+import openerp
343 import openerp.tools as tools
344 import openerp.modules
345 import print_xml
346@@ -43,11 +44,16 @@
347
348 _reports = {}
349
350- def __init__(self, name):
351- if not name.startswith('report.'):
352- raise Exception('ConceptionError, bad report name, should start with "report."')
353- assert name not in self._reports, 'The report "%s" already exists!' % name
354- self._reports[name] = self
355+ def __init__(self, name, register=True):
356+ if register:
357+ assert openerp.conf.deprecation.allow_report_int_registration
358+ assert name.startswith('report.'), 'Report names should start with "report.".'
359+ assert name not in self._reports, 'The report "%s" already exists.' % name
360+ self._reports[name] = self
361+ else:
362+ # The report is instanciated at each use site, which is ok.
363+ pass
364+
365 self.__name = name
366
367 self.name = name
368@@ -65,8 +71,8 @@
369 XML -> DATAS -> RML -> PDF -> HTML
370 using a XSL:RML transformation
371 """
372- def __init__(self, name, table, tmpl, xsl):
373- super(report_rml, self).__init__(name)
374+ def __init__(self, name, table, tmpl, xsl, register=True):
375+ super(report_rml, self).__init__(name, register=register)
376 self.table = table
377 self.internal_header=False
378 self.tmpl = tmpl
379
380=== modified file 'openerp/report/print_xml.py'
381--- openerp/report/print_xml.py 2012-02-08 17:04:56 +0000
382+++ openerp/report/print_xml.py 2013-03-27 15:55:25 +0000
383@@ -264,7 +264,7 @@
384 def parse_tree(self, ids, model, context=None):
385 if not context:
386 context={}
387- browser = self.pool.get(model).browse(self.cr, self.uid, ids, context)
388+ browser = self.pool[model].browse(self.cr, self.uid, ids, context)
389 self.parse_node(self.dom, self.doc, browser)
390
391 def parse_string(self, xml, ids, model, context=None):
392
393=== modified file 'openerp/report/report_sxw.py'
394--- openerp/report/report_sxw.py 2013-02-08 13:57:04 +0000
395+++ openerp/report/report_sxw.py 2013-03-27 15:55:25 +0000
396@@ -388,8 +388,19 @@
397 self.setCompany(objects[0].company_id)
398
399 class report_sxw(report_rml, preprocess.report):
400- def __init__(self, name, table, rml=False, parser=rml_parse, header='external', store=False):
401- report_rml.__init__(self, name, table, rml, '')
402+ """
403+ The register=True kwarg has been added to help remove the
404+ openerp.netsvc.LocalService() indirection and the related
405+ openerp.report.interface.report_int._reports dictionary:
406+ report_sxw registered in XML with auto=False are also registered in Python.
407+ In that case, they are registered in the above dictionary. Since
408+ registration is automatically done upon instanciation, and that
409+ instanciation is needed before rendering, a way was needed to
410+ instanciate-without-register a report. In the future, no report
411+ should be registered in the above dictionary and it will be dropped.
412+ """
413+ def __init__(self, name, table, rml=False, parser=rml_parse, header='external', store=False, register=True):
414+ report_rml.__init__(self, name, table, rml, '', register=register)
415 self.name = name
416 self.parser = parser
417 self.header = header
418
419=== modified file 'openerp/service/report.py'
420--- openerp/service/report.py 2013-02-14 15:35:11 +0000
421+++ openerp/service/report.py 2013-03-27 15:55:25 +0000
422@@ -5,8 +5,8 @@
423 import sys
424 import threading
425
426-import openerp.netsvc
427 import openerp.pooler
428+import openerp.report
429 from openerp import tools
430
431 import security
432@@ -51,8 +51,7 @@
433
434 cr = openerp.pooler.get_db(db).cursor()
435 try:
436- obj = openerp.netsvc.LocalService('report.'+object)
437- (result, format) = obj.create(cr, uid, ids, datas, context)
438+ result, format = openerp.report.render_report(cr, uid, ids, object, datas, context)
439 if not result:
440 tb = sys.exc_info()
441 self_reports[id]['exception'] = openerp.exceptions.DeferredException('RML is not available at specified location or not enough data to print!', tb)
442@@ -90,8 +89,7 @@
443 def go(id, uid, ids, datas, context):
444 cr = openerp.pooler.get_db(db).cursor()
445 try:
446- obj = openerp.netsvc.LocalService('report.'+object)
447- (result, format) = obj.create(cr, uid, ids, datas, context)
448+ result, format = openerp.report.render_report(cr, uid, ids, object, datas, context)
449 if not result:
450 tb = sys.exc_info()
451 self_reports[id]['exception'] = openerp.exceptions.DeferredException('RML is not available at specified location or not enough data to print!', tb)
452
453=== modified file 'openerp/tools/convert.py'
454--- openerp/tools/convert.py 2013-03-27 15:54:24 +0000
455+++ openerp/tools/convert.py 2013-03-27 15:55:25 +0000
456@@ -294,7 +294,8 @@
457 res[dest] = rec.get(f,'').encode('utf8')
458 assert res[dest], "Attribute %s of report is empty !" % (f,)
459 for field,dest in (('rml','report_rml'),('file','report_rml'),('xml','report_xml'),('xsl','report_xsl'),
460- ('attachment','attachment'),('attachment_use','attachment_use'), ('usage','usage')):
461+ ('attachment','attachment'),('attachment_use','attachment_use'), ('usage','usage'),
462+ ('report_type', 'report_type'), ('parser', 'parser')):
463 if rec.get(field):
464 res[dest] = rec.get(field).encode('utf8')
465 if rec.get('auto'):
466@@ -304,8 +305,6 @@
467 res['report_sxw_content'] = sxw_content
468 if rec.get('header'):
469 res['header'] = eval(rec.get('header','False'))
470- if rec.get('report_type'):
471- res['report_type'] = rec.get('report_type')
472
473 res['multi'] = rec.get('multi') and eval(rec.get('multi','False'))
474
475
476=== modified file 'openerp/tools/test_reports.py'
477--- openerp/tools/test_reports.py 2012-11-30 15:29:37 +0000
478+++ openerp/tools/test_reports.py 2013-03-27 15:55:25 +0000
479@@ -25,7 +25,7 @@
480 through the code of yaml tests.
481 """
482
483-import openerp.netsvc as netsvc
484+import openerp.report
485 import openerp.tools as tools
486 import logging
487 import openerp.pooler as pooler
488@@ -49,8 +49,8 @@
489 rname_s = rname[7:]
490 else:
491 rname_s = rname
492- _logger.log(netsvc.logging.TEST, " - Trying %s.create(%r)", rname, ids)
493- res = netsvc.LocalService(rname).create(cr, uid, ids, data, context)
494+ _logger.log(logging.TEST, " - Trying %s.create(%r)", rname, ids)
495+ res = openerp.report.render_report(cr, uid, ids, rname_s, data, context)
496 if not isinstance(res, tuple):
497 raise RuntimeError("Result of %s.create() should be a (data,format) tuple, now it is a %s" % \
498 (rname, type(res)))
499@@ -92,7 +92,7 @@
500 _logger.warning("Report %s produced a \"%s\" chunk, cannot examine it", rname, res_format)
501 return False
502
503- _logger.log(netsvc.logging.TEST, " + Report %s produced correctly.", rname)
504+ _logger.log(logging.TEST, " + Report %s produced correctly.", rname)
505 return True
506
507 def try_report_action(cr, uid, action_id, active_model=None, active_ids=None,
508@@ -126,7 +126,7 @@
509 pool = pooler.get_pool(cr.dbname)
510
511 def log_test(msg, *args):
512- _logger.log(netsvc.logging.TEST, " - " + msg, *args)
513+ _logger.log(logging.TEST, " - " + msg, *args)
514
515 datas = {}
516 if active_model:
517
518=== modified file 'openerp/tools/yaml_import.py'
519--- openerp/tools/yaml_import.py 2012-12-01 11:35:24 +0000
520+++ openerp/tools/yaml_import.py 2013-03-27 15:55:25 +0000
521@@ -5,6 +5,7 @@
522 from datetime import datetime, timedelta
523 import logging
524
525+import openerp
526 import openerp.pooler as pooler
527 import openerp.sql_db as sql_db
528 import misc
529@@ -281,7 +282,6 @@
530 return record_dict
531
532 def process_record(self, node):
533- import openerp.osv as osv
534 record, fields = node.items()[0]
535 model = self.get_model(record.model)
536
537@@ -543,7 +543,14 @@
538 python, statements = node.items()[0]
539 model = self.get_model(python.model)
540 statements = statements.replace("\r\n", "\n")
541- code_context = { 'model': model, 'cr': self.cr, 'uid': self.uid, 'log': self._log, 'context': self.context }
542+ code_context = {
543+ 'model': model,
544+ 'cr': self.cr,
545+ 'uid': self.uid,
546+ 'log': self._log,
547+ 'context': self.context,
548+ 'openerp': openerp,
549+ }
550 code_context.update({'self': model}) # remove me when no !python block test uses 'self' anymore
551 try:
552 code_obj = compile(statements, self.filename, 'exec')