Add pool to wizard and first wizard for module (update list)
This commit is contained in:
1 parent
78f9d1e820
commit
72211bb8bf
6 files changed
+305
-108
No files matched your search
@@ -7,6 +7,7 @@ from trytond.osv import fields, OSV
|
||||
import trytond.tools as tools
|
||||
from trytond.module import ADDONS_PATH
|
||||
from trytond.osv.orm import ExceptORM
|
||||
from trytond.wizard import Wizard
|
||||
|
||||
VER_REGEXP = re.compile(
|
||||
"^(\\d+)((\\.\\d+)*)([a-z]?)((_(pre|p|beta|alpha|rc)\\d*)*)(-r(\\d+))?$")
|
||||
@@ -536,3 +537,89 @@ class ModuleDependency(OSV):
|
||||
}
|
||||
|
||||
ModuleDependency()
|
||||
|
||||
|
||||
class ModuleUpdateList(Wizard):
|
||||
"Update module list"
|
||||
_name = 'ir.module.module.update_list'
|
||||
|
||||
arch = '''<?xml version="1.0"?>
|
||||
<form string="Scan for new modules">
|
||||
<label string="This function will check for new modules in the 'addons' path and on module repositories:" colspan="4" align="0.0"/>
|
||||
<field name="repositories" colspan="4" nolabel="1"/>
|
||||
</form>'''
|
||||
fields = {
|
||||
'repositories': {'type': 'text', 'string': 'Repositories', 'readonly': True},
|
||||
}
|
||||
|
||||
arch_module = '''<?xml version="1.0"?>
|
||||
<form string="New modules">
|
||||
<field name="update" colspan="4"/>
|
||||
<field name="add" colspan="4"/>
|
||||
</form>'''
|
||||
|
||||
fields_module = {
|
||||
'update': {'type': 'integer', 'string': 'Number of modules updated', 'readonly': True},
|
||||
'add': {'type': 'integer', 'string': 'Number of modules added', 'readonly': True},
|
||||
}
|
||||
|
||||
def _update_module(self, cr, uid, data, context):
|
||||
module_obj = self.pool.get('ir.module.module')
|
||||
update, add = module_obj.update_list(cr, uid)
|
||||
return {'update': update, 'add': add}
|
||||
|
||||
def _action_module_open(self, cr, uid, data, context):
|
||||
return {
|
||||
'domain': str([]),
|
||||
'name': 'Module List',
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'ir.module.module',
|
||||
'view_id': False,
|
||||
'type': 'ir.actions.act_window',
|
||||
}
|
||||
|
||||
def _get_repositories(self, cr, uid, data, context):
|
||||
repository_obj = self.pool.get('ir.module.repository')
|
||||
ids = repository_obj.search(cr, uid, [])
|
||||
res = repository_obj.read(cr, uid, ids, ['name', 'url'], context)
|
||||
return {
|
||||
'repositories': '\n'.join([x['name']+': '+x['url'] \
|
||||
for x in res]),
|
||||
}
|
||||
|
||||
states = {
|
||||
'init': {
|
||||
'actions': [_get_repositories],
|
||||
'result': {
|
||||
'type': 'form',
|
||||
'arch': arch,
|
||||
'fields': fields,
|
||||
'state': [
|
||||
('end', 'Cancel', 'gtk-cancel'),
|
||||
('update', 'Check new modules', 'gtk-ok', True),
|
||||
]
|
||||
}
|
||||
},
|
||||
'update': {
|
||||
'actions': [_update_module],
|
||||
'result': {
|
||||
'type': 'form',
|
||||
'arch': arch_module,
|
||||
'fields': fields_module,
|
||||
'state': [
|
||||
('open_window', 'Ok', 'gtk-ok', True),
|
||||
]
|
||||
}
|
||||
},
|
||||
'open_window': {
|
||||
'actions': [],
|
||||
'result': {
|
||||
'type': 'action',
|
||||
'action': _action_module_open,
|
||||
'state':'end',
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
ModuleUpdateList()
|
||||
@@ -95,5 +95,13 @@
|
||||
</record>
|
||||
<menuitem name="Administration/IR/Modules/"
|
||||
action="act_module_form" id="menu_module_form"/>
|
||||
<record model="ir.actions.wizard" id="act_module_update_list">
|
||||
<field name="name">Update Module List</field>
|
||||
<field name="wiz_name">ir.module.module.update_list</field>
|
||||
</record>
|
||||
<menuitem name="Administration/IR/Modules/Update Module List"
|
||||
action="act_module_update_list"
|
||||
type="wizard"
|
||||
id="menu_module_update_list"/>
|
||||
</data>
|
||||
</terp>
|
||||
@@ -168,6 +168,8 @@ def load_module_graph(cursor, graph, **kwargs):
|
||||
sys.stdout.flush()
|
||||
pool = pooler.get_pool(cursor.dbname)
|
||||
modules = pool.instanciate(module)
|
||||
pool_wizard = pooler.get_pool_wizard(cursor.dbname)
|
||||
wizards = pool_wizard.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()) \
|
||||
|
||||
+15
-1
@@ -3,8 +3,10 @@ from netsvc import Logger, LOG_INFO
|
||||
|
||||
_DB = {}
|
||||
_POOL = {}
|
||||
_POOL_WIZARD = {}
|
||||
|
||||
def get_db_and_pool(db_name, force_demo=False, update_module=False):
|
||||
def get_db_and_pool(db_name, force_demo=False, update_module=False,
|
||||
wizard=False):
|
||||
if db_name in _DB:
|
||||
database = _DB[db_name]
|
||||
else:
|
||||
@@ -15,12 +17,18 @@ 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]
|
||||
else:
|
||||
Logger().notify_channel('pooler', LOG_INFO,
|
||||
'Instanciate pooler for %s' % (db_name))
|
||||
from osv.osv import OSVService
|
||||
pool = OSVService()
|
||||
_POOL[db_name] = pool
|
||||
|
||||
from wizard import WizardService
|
||||
pool_wizard = WizardService()
|
||||
_POOL_WIZARD[db_name] = pool_wizard
|
||||
|
||||
from module import load_modules
|
||||
load_modules(database, force_demo, update_module)
|
||||
|
||||
@@ -28,6 +36,8 @@ def get_db_and_pool(db_name, force_demo=False, update_module=False):
|
||||
import report
|
||||
#report.interface.register_all(database)
|
||||
pool.get('ir.cron').pool_jobs(database.dbname)
|
||||
if wizard:
|
||||
return database, pool_wizard
|
||||
return database, pool
|
||||
|
||||
def restart_pool(db_name, force_demo=False, update_module=False):
|
||||
@@ -57,3 +67,7 @@ def get_db(db_name):
|
||||
def get_pool(db_name, force_demo=False, update_module=False):
|
||||
pool = get_db_and_pool(db_name, force_demo, update_module)[1]
|
||||
return pool
|
||||
|
||||
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
|
||||
@@ -16,9 +16,9 @@ class Wizard(Service):
|
||||
|
||||
def _execute(self, database, user, wiz_id, datas, action, context):
|
||||
self.wiz_datas[wiz_id].update(datas)
|
||||
wiz = LocalService('wizard.' + self.wiz_name[wiz_id])
|
||||
return wiz.execute(database, user, self.wiz_datas[wiz_id], action,
|
||||
context)
|
||||
wiz = LocalService('wizard_proxy')
|
||||
return wiz.execute(database, user, self.wiz_name[wiz_id],
|
||||
self.wiz_datas[wiz_id], action, context)
|
||||
|
||||
def create(self, database, user, passwd, wiz_name, datas=None):
|
||||
security.check(database, user, passwd)
|
||||
|
||||
+190
-104
@@ -6,6 +6,11 @@ from xml import dom
|
||||
from trytond.osv import ExceptORM, ExceptOSV
|
||||
import sys
|
||||
|
||||
MODULE_LIST = []
|
||||
MODULE_CLASS_LIST = {}
|
||||
CLASS_POOL = {}
|
||||
|
||||
|
||||
class ExceptWizard(Exception):
|
||||
def __init__(self, name, value):
|
||||
Exception.__init__(self)
|
||||
@@ -16,107 +21,23 @@ class ExceptWizard(Exception):
|
||||
except_wizard = ExceptWizard
|
||||
|
||||
class WizardService(Service):
|
||||
states = {}
|
||||
name = ""
|
||||
|
||||
def __init__(self):
|
||||
self.wiz_name = self.name
|
||||
assert not service_exist(self.wiz_name), \
|
||||
'The wizard "%s" already exists!' % self.name
|
||||
Service.__init__(self, self.wiz_name)
|
||||
self.object_name_pool = {}
|
||||
self.module_obj_list = {}
|
||||
Service.__init__(self, 'wizard_proxy')
|
||||
Service.join_group(self, 'web-services')
|
||||
Service.export_method(self, self.execute)
|
||||
|
||||
def translate_view(self, cursor, node, state, lang):
|
||||
translation_obj = pooler.get_pool(cursor.dbname).get('ir.translation')
|
||||
if node.nodeType == node.ELEMENT_NODE:
|
||||
if node.hasAttribute('string') \
|
||||
and node.getAttribute('string'):
|
||||
res_trans = translation_obj._get_source(cursor,
|
||||
self.wiz_name + ',' + state, 'wizard_view', lang)
|
||||
if res_trans:
|
||||
node.setAttribute('string', res_trans.decode('utf8'))
|
||||
for child_node in node.childNodes:
|
||||
self.translate_view(cursor, child_node, state, lang)
|
||||
|
||||
def execute_cr(self, cursor, user, data, state='init', context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
res = {}
|
||||
pool = pooler.get_pool(cursor.dbname)
|
||||
values_obj = pool.get('ir.values')
|
||||
translation_obj = pool.get('ir.translation')
|
||||
def execute_cr(self, cursor, user, wizard_name, data, state='init',
|
||||
context=None):
|
||||
try:
|
||||
state_def = self.states[state]
|
||||
result_def = copy.copy(state_def.get('result', {}))
|
||||
|
||||
# iterate through the list of actions defined for this state
|
||||
for action in state_def.get('actions', []):
|
||||
# execute them
|
||||
action_res = action(self, cursor, user, data, context)
|
||||
assert isinstance(action_res, dict), \
|
||||
'The return value of wizard actions ' \
|
||||
'should be a dictionary'
|
||||
result_def.update(action_res)
|
||||
|
||||
res['datas'] = result_def.get('datas', {})
|
||||
|
||||
lang = context.get('lang', 'en_US')
|
||||
if result_def['type'] == 'action':
|
||||
res['action'] = result_def['action'](self, cursor, user, data,
|
||||
context)
|
||||
elif result_def['type'] == 'form':
|
||||
fields = copy.copy(result_def['fields'])
|
||||
arch = copy.copy(result_def['arch'])
|
||||
button_list = copy.copy(result_def['state'])
|
||||
|
||||
defaults = values_obj.get(cursor, user, 'default',
|
||||
False, [('wizard.'+self.wiz_name, False)])
|
||||
default_values = dict([(x[1], x[2]) for x in defaults])
|
||||
for val in fields.keys():
|
||||
if 'default' in fields[val]:
|
||||
# execute default method for this field
|
||||
if callable(fields[val]['default']):
|
||||
fields[val]['value'] = fields[val]['default']\
|
||||
(self, cursor, user, data, state, context)
|
||||
else:
|
||||
fields[val]['value'] = fields[val]['default']
|
||||
del fields[val]['default']
|
||||
if val in default_values:
|
||||
fields[val]['value'] = default_values[val]
|
||||
if 'selection' in fields[val]:
|
||||
if callable(fields[val]['selection']):
|
||||
fields[val] = copy.copy(fields[val])
|
||||
fields[val]['selection'] = fields[val]['selection']\
|
||||
(self, cursor, user, data, state, context)
|
||||
|
||||
# translate fields
|
||||
for field in fields:
|
||||
res_trans = translation_obj._get_source(cursor, user,
|
||||
self.wiz_name + ',' + state + ',' + field,
|
||||
'wizard_field', lang)
|
||||
if res_trans:
|
||||
fields[field]['string'] = res_trans
|
||||
|
||||
# translate arch
|
||||
doc = dom.minidom.parseString(arch)
|
||||
self.translate_view(cursor, doc, state, lang)
|
||||
arch = doc.toxml()
|
||||
|
||||
# translate buttons
|
||||
for i, button in enumerate(button_list):
|
||||
button_name = button[0]
|
||||
res_trans = translation_obj._get_source(cursor, user,
|
||||
self.wiz_name + ',' + state + ',' + button_name,
|
||||
'wizard_button', lang)
|
||||
if res_trans:
|
||||
button = list(button)
|
||||
button[1] = res_trans
|
||||
button_list[i] = tuple(button)
|
||||
|
||||
res['fields'] = fields
|
||||
res['arch'] = arch
|
||||
res['state'] = button_list
|
||||
|
||||
wizard = pooler.get_pool_wizard(cursor.dbname).get(wizard_name)
|
||||
if not wizard:
|
||||
self.abort_response('Wizard Error', 'warning',
|
||||
'Wizard %s doesn\'t exist' % str(wizard_name))
|
||||
res = wizard.execute(cursor, user, data, state, context)
|
||||
return res
|
||||
except ExceptORM, inst:
|
||||
self.abort_response(inst.name, 'warning', inst.value)
|
||||
except ExceptOSV, inst:
|
||||
@@ -131,17 +52,14 @@ class WizardService(Service):
|
||||
'Exception in call: ' + tb_s)
|
||||
raise
|
||||
|
||||
if result_def['type'] == 'choice':
|
||||
next_state = result_def['next_state'](self, cursor, user,
|
||||
data, context)
|
||||
return self.execute_cr(cursor, user, data, next_state, context)
|
||||
return res
|
||||
|
||||
def execute(self, dbname, user, data, state='init', context=None):
|
||||
def execute(self, dbname, user, wizard_name, data, state='init',
|
||||
context=None):
|
||||
cursor = pooler.get_db(dbname).cursor()
|
||||
pool = pooler.get_pool_wizard(dbname)
|
||||
try:
|
||||
try:
|
||||
res = self.execute_cr(cursor, user, data, state, context)
|
||||
res = pool.execute_cr(cursor, user, wizard_name, data, state,
|
||||
context)
|
||||
cursor.commit()
|
||||
except Exception:
|
||||
cursor.rollback()
|
||||
@@ -149,3 +67,171 @@ class WizardService(Service):
|
||||
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 Wizard(object):
|
||||
_name = ""
|
||||
states = {}
|
||||
|
||||
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__
|
||||
new_states = copy.copy(getattr(pool.get(cls._name), 'states'))
|
||||
for i in (
|
||||
'actions',
|
||||
'result',
|
||||
):
|
||||
new = copy.copy(getattr(new_states, i))
|
||||
if hasattr(new, 'update'):
|
||||
new.update(cls.__dict__.get(i, {}))
|
||||
else:
|
||||
new.extend(cls.__dict__.get(i, []))
|
||||
new_states[i] = new
|
||||
cls = type(cls._name, (cls, parent_class), {'states': new_states})
|
||||
|
||||
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(Wizard, self).__init__()
|
||||
|
||||
def translate_view(self, cursor, node, state, lang):
|
||||
translation_obj = pooler.get_pool(cursor.dbname).get('ir.translation')
|
||||
if node.nodeType == node.ELEMENT_NODE:
|
||||
if node.hasAttribute('string') \
|
||||
and node.getAttribute('string'):
|
||||
res_trans = translation_obj._get_source(cursor,
|
||||
self._name + ',' + state, 'wizard_view', lang)
|
||||
if res_trans:
|
||||
node.setAttribute('string', res_trans.decode('utf8'))
|
||||
for child_node in node.childNodes:
|
||||
self.translate_view(cursor, child_node, state, lang)
|
||||
|
||||
def execute(self, cursor, user, data, state='init', context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
res = {}
|
||||
values_obj = self.pool.get('ir.values')
|
||||
translation_obj = self.pool.get('ir.translation')
|
||||
|
||||
state_def = self.states[state]
|
||||
result_def = copy.copy(state_def.get('result', {}))
|
||||
|
||||
# iterate through the list of actions defined for this state
|
||||
for action in state_def.get('actions', []):
|
||||
# execute them
|
||||
action_res = action(self, cursor, user, data, context)
|
||||
assert isinstance(action_res, dict), \
|
||||
'The return value of wizard actions ' \
|
||||
'should be a dictionary'
|
||||
result_def.update(action_res)
|
||||
|
||||
res = copy.copy(result_def)
|
||||
res['datas'] = result_def.get('datas', {})
|
||||
|
||||
lang = context.get('lang', 'en_US')
|
||||
if result_def['type'] == 'action':
|
||||
res['action'] = result_def['action'](self, cursor, user, data,
|
||||
context)
|
||||
elif result_def['type'] == 'form':
|
||||
fields = copy.copy(result_def['fields'])
|
||||
arch = copy.copy(result_def['arch'])
|
||||
button_list = copy.copy(result_def['state'])
|
||||
|
||||
defaults = values_obj.get(cursor, user, 'default',
|
||||
False, [(self._name, False)])
|
||||
default_values = dict([(x[1], x[2]) for x in defaults])
|
||||
for val in fields.keys():
|
||||
if 'default' in fields[val]:
|
||||
# execute default method for this field
|
||||
if callable(fields[val]['default']):
|
||||
fields[val]['value'] = fields[val]['default']\
|
||||
(self, cursor, user, data, state, context)
|
||||
else:
|
||||
fields[val]['value'] = fields[val]['default']
|
||||
del fields[val]['default']
|
||||
if val in default_values:
|
||||
fields[val]['value'] = default_values[val]
|
||||
if 'selection' in fields[val]:
|
||||
if callable(fields[val]['selection']):
|
||||
fields[val] = copy.copy(fields[val])
|
||||
fields[val]['selection'] = fields[val]['selection']\
|
||||
(self, cursor, user, data, state, context)
|
||||
|
||||
# translate fields
|
||||
for field in fields:
|
||||
res_trans = translation_obj._get_source(cursor, user,
|
||||
self._name + ',' + state + ',' + field,
|
||||
'wizard_field', lang)
|
||||
if res_trans:
|
||||
fields[field]['string'] = res_trans
|
||||
|
||||
# translate arch
|
||||
doc = dom.minidom.parseString(arch)
|
||||
self.translate_view(cursor, doc, state, lang)
|
||||
arch = doc.toxml()
|
||||
|
||||
# translate buttons
|
||||
for i, button in enumerate(button_list):
|
||||
button_name = button[0]
|
||||
res_trans = translation_obj._get_source(cursor, user,
|
||||
self._name + ',' + state + ',' + button_name,
|
||||
'wizard_button', lang)
|
||||
if res_trans:
|
||||
button = list(button)
|
||||
button[1] = res_trans
|
||||
button_list[i] = tuple(button)
|
||||
|
||||
res['fields'] = fields
|
||||
res['arch'] = arch
|
||||
res['state'] = button_list
|
||||
if result_def['type'] == 'choice':
|
||||
next_state = result_def['next_state'](self, cursor, user,
|
||||
data, context)
|
||||
return self.execute(cursor, user, data, next_state, context)
|
||||
return res
|
||||
Reference in new issue
Block a user