This commit is contained in:
Bertrand Chenal committed 2008-01-07 03:26:04 +01:00
commit 57d3f138ae
9 files changed
+169 -89

No files matched your search

+1 -1
View File
@@ -77,7 +77,7 @@ INHERITS (ir_actions);
CREATE TABLE ir_act_report (
model varchar(64) NOT NULL,
report_name varchar(64) NOT NULL,
report_odt varchar(64),
report varchar(64),
auto boolean default true,
primary key(id)
)
+7 -15
View File
@@ -68,8 +68,8 @@ class ActionKeyword(OSV):
.read(cursor, user, action_keyword.action.id,
context=context))
if action_keyword.action.type == 'ir.actions.report':
del res[-1]['report_odt_content_data']
del res[-1]['report_odt_content']
del res[-1]['report_content_data']
del res[-1]['report_content']
return res
ActionKeyword()
@@ -102,21 +102,17 @@ class ActionsReport(OSV):
'type': fields.char('Report Type', size=32, required=True),
'model': fields.char('Model', size=64, required=True),
'report_name': fields.char('Internal Name', size=64, required=True),
'report_odt': fields.Char('ODT path', size=128),
'report_odt_content_data': fields.binary('ODT content'),
'report_odt_content': fields.function(_report_content,
'report': fields.Char('Path', size=128),
'report_content_data': fields.binary('Content'),
'report_content': fields.function(_report_content,
fnct_inv=_report_content_inv, method=True,
type='binary', string='ODT content',),
type='binary', string='Content',),
'auto': fields.boolean('Automatic', required=True),
'multi': fields.boolean('On multiple doc.',
help="If set to true, the action will not be displayed " \
"on the right toolbar of a form views.")
}
_defaults = {
'type': lambda *a: 'ir.actions.report',
'multi': lambda *a: False,
'auto': lambda *a: True,
'report_odt_content': lambda *a: False,
'report_content': lambda *a: False,
}
ActionsReport()
@@ -215,13 +211,9 @@ class ActionsWizard(OSV):
translate=True),
'type': fields.char('Action type', size=32, required=True),
'wiz_name': fields.char('Wizard name', size=64, required=True),
'multi': fields.boolean('Action on multiple doc.',
help="If set to true, the wizard will not be displayed \n" \
"on the right toolbar of a form views.")
}
_defaults = {
'type': lambda *a: 'ir.actions.wizard',
'multi': lambda *a: False,
}
ActionsWizard()
+4 -2
View File
@@ -66,8 +66,9 @@
<form string="Report">
<field name="name" select="1"/>
<field name="type" select="1"/>
<field name="report_name" select="1"/>
<field name="report_odt"/>
<field name="model" select="1"/>
<field name="report_name" select="2"/>
<field name="report"/>
<field name="auto"/>
</form>
]]>
@@ -81,6 +82,7 @@
<tree string="Report xml">
<field name="name"/>
<field name="type"/>
<field name="model"/>
<field name="report_name"/>
</tree>
]]>
+2
View File
@@ -170,6 +170,8 @@ def load_module_graph(cursor, graph):
modules = pool.instanciate(module)
pool_wizard = pooler.get_pool_wizard(cursor.dbname)
wizards = pool_wizard.instanciate(module, pool)
pool_report = pooler.get_pool_report(cursor.dbname)
reports = pool_report.instanciate(module, pool)
cursor.execute('SELECT state, demo FROM ir_module_module WHERE name = %s',
(module,))
(package_state, package_demo) = (cursor.rowcount and cursor.fetchone()) \
+13 -1
View File
@@ -4,9 +4,10 @@ from netsvc import Logger, LOG_INFO
_DB = {}
_POOL = {}
_POOL_WIZARD = {}
_POOL_REPORT = {}
def get_db_and_pool(db_name, force_demo=False, update_module=False,
wizard=False):
wizard=False, report=False):
if db_name in _DB:
database = _DB[db_name]
else:
@@ -18,6 +19,7 @@ def get_db_and_pool(db_name, force_demo=False, update_module=False,
if db_name in _POOL:
pool = _POOL[db_name]
pool_wizard = _POOL_WIZARD[db_name]
pool_report = _POOL_REPORT[db_name]
else:
Logger().notify_channel('pooler', LOG_INFO,
'Instanciate pooler for %s' % (db_name))
@@ -29,6 +31,10 @@ def get_db_and_pool(db_name, force_demo=False, update_module=False,
pool_wizard = WizardService()
_POOL_WIZARD[db_name] = pool_wizard
from report import ReportService
pool_report = ReportService()
_POOL_REPORT[db_name] = pool_report
from module import load_modules
load_modules(database, force_demo, update_module)
@@ -38,6 +44,8 @@ def get_db_and_pool(db_name, force_demo=False, update_module=False,
pool.get('ir.cron').pool_jobs(database.dbname)
if wizard:
return database, pool_wizard
if report:
return database, pool_report
return database, pool
def restart_pool(db_name, force_demo=False, update_module=False):
@@ -71,3 +79,7 @@ def get_pool(db_name, force_demo=False, update_module=False):
def get_pool_wizard(db_name, force_demo=False, update_module=False):
pool = get_db_and_pool(db_name, force_demo, update_module, wizard=True)[1]
return pool
def get_pool_report(db_name, force_demo=False, update_module=False):
pool = get_db_and_pool(db_name, force_demo, update_module, report=True)[1]
return pool
+1
View File
@@ -0,0 +1 @@
from report import *
+137
View File
@@ -0,0 +1,137 @@
"Report"
from trytond.netsvc import Service, service_exist, Logger, LOG_ERROR
from trytond import pooler
import copy
from xml import dom
from trytond.osv import ExceptORM, ExceptOSV, OSV
import sys
import base64
MODULE_LIST = []
MODULE_CLASS_LIST = {}
CLASS_POOL = {}
class ReportService(Service):
def __init__(self):
self.object_name_pool = {}
self.module_obj_list = {}
Service.__init__(self, 'report_proxy')
Service.join_group(self, 'web-services')
Service.export_method(self, self.execute)
def execute_cr(self, cursor, user, report_name, ids, datas, context=None):
try:
report = pooler.get_pool_report(cursor.dbname).get(report_name)
if not report:
self.abort_response('Report Error', 'warning',
'Report %s doesn\'t exist' % str(report_name))
res = report.execute(cursor, user, ids, datas, context)
return res
except ExceptORM, inst:
self.abort_response(inst.name, 'warning', inst.value)
except ExceptOSV, inst:
self.abort_response(inst.name, inst.exc_type, inst.value)
except:
import traceback
tb_s = reduce(lambda x, y: x+y, traceback.format_exception(
sys.exc_type, sys.exc_value, sys.exc_traceback))
Logger().notify_channel("web-services", LOG_ERROR,
'Exception in call: ' + tb_s)
raise
def execute(self, dbname, user, report_name, ids, datas, context=None):
cursor = pooler.get_db(dbname).cursor()
pool = pooler.get_pool_report(dbname)
try:
try:
res = pool.execute_cr(cursor, user, report_name, ids, datas, context)
cursor.commit()
except Exception:
cursor.rollback()
raise
finally:
cursor.close()
return res
def add(self, name, object_name_inst):
"""
adds a new obj instance to the obj pool.
if it already existed, the instance is replaced
"""
if self.object_name_pool.has_key(name):
del self.object_name_pool[name]
self.object_name_pool[name] = object_name_inst
module = str(object_name_inst.__class__)[6:]
module = module[:len(module)-1]
module = module.split('.')[0][2:]
self.module_obj_list.setdefault(module, []).append(object_name_inst)
def get(self, name):
return self.object_name_pool.get(name, None)
def instanciate(self, module, pool_obj):
res = []
class_list = MODULE_CLASS_LIST.get(module, [])
for klass in class_list:
res.append(klass.create_instance(self, module, pool_obj))
return res
class Report(object):
_name = ""
def __new__(cls):
for module in cls.__module__.split('.'):
if module != 'trytond' and module != 'addons':
break
if not hasattr(cls, '_module'):
cls._module = module
MODULE_CLASS_LIST.setdefault(cls._module, []).append(cls)
CLASS_POOL[cls._name] = cls
if module not in MODULE_LIST:
MODULE_LIST.append(cls._module)
return None
def create_instance(cls, pool, module, pool_obj):
"""
try to apply inheritancy at the instanciation level and
put objs in the pool var
"""
if pool.get(cls._name):
parent_class = pool.get(cls._name).__class__
nattr = {}
for i in (
'_context',
):
new = copy.copy(getattr(pool.get(cls._name), i))
if hasattr(new, 'update'):
new.update(cls.__dict__.get(i, {}))
else:
new.extend(cls.__dict__.get(i, []))
nattr[i] = new
cls = type(cls._name, (cls, parent_class), nattr)
obj = object.__new__(cls)
obj.__init__(pool, pool_obj)
return obj
create_instance = classmethod(create_instance)
def __init__(self, pool, pool_obj):
pool.add(self._name, self)
self.pool = pool_obj
super(Report, self).__init__()
def execute(self, cursor, user, ids, datas, context=None):
action_report_obj = self.pool.get('ir.actions.report')
action_report_ids = action_report_obj.search(cursor, user, [
('report_name', '=', self._name)
], context=context)
action_report = action_report_obj.browse(cursor, user,
action_report_ids[0], context=context)
#TODO add parser
type, data = 'odt', action_report.report_content
return (type, base64.encodestring(data))
View File
Whitespace-only changes.
+4 -70
View File
@@ -1,10 +1,5 @@
from trytond.netsvc import Service, LocalService
from trytond import security
import threading
import thread
from trytond import pooler
from trytond.config import CONFIG
import base64
class Report(Service):
@@ -12,71 +7,10 @@ class Report(Service):
def __init__(self, name='report'):
Service.__init__(self, name)
Service.join_group(self, 'web-services')
Service.export_method(self, self.report)
Service.export_method(self, self.report_get)
self._reports = {}
self.max_id = 0
self.id_protect = threading.Semaphore()
Service.export_method(self, self.execute)
def report(self, database, user, passwd, object_name, ids, datas=None,
def execute(self, database, user, passwd, report_name, ids, datas=None,
context=None):
if datas is None:
datas = {}
if context is None:
context = {}
security.check(database, user, passwd)
self.id_protect.acquire()
self.max_id += 1
report_id = self.max_id
self.id_protect.release()
self._reports[report_id] = {
'user': user,
'result': False,
'state': False,
}
def _go(report_id, user, ids, datas, context):
cursor = pooler.get_db(database).cursor()
obj = LocalService('report.' + object_name)
(result, format) = obj.create(cursor, user, ids, datas, context)
cursor.close()
self._reports[report_id]['result'] = result
self._reports[report_id]['format'] = format
self._reports[report_id]['state'] = True
return True
thread.start_new_thread(_go, (report_id, user, ids, datas, context))
return report_id
def _check_report(self, report_id):
result = self._reports[report_id]
res = {'state': result['state']}
if res['state']:
if CONFIG['reportgz']:
import zlib
res2 = zlib.compress(result['result'])
res['code'] = 'zlib'
else:
#CHECKME: why is this needed???
if isinstance(result['result'], unicode):
res2 = result['result'].encode('latin1', 'replace')
else:
res2 = result['result']
if res2:
res['result'] = base64.encodestring(res2)
res['format'] = result['format']
del self._reports[report_id]
return res
def report_get(self, database, user, passwd, report_id):
security.check(database, user, passwd)
if report_id in self._reports:
if self._reports[report_id]['uid'] == user:
return self._check_report(report_id)
else:
raise Exception, 'AccessDenied'
else:
raise Exception, 'ReportNotFound'
report = LocalService('report_proxy')
return report.execute(database, user, report_name, ids, datas, context)