return ElementTree.tostring(root, 'utf-8'), files_timestamp
-def concat_files(file_list):
+def concat_files(file_list, reader=None):
""" Concatenate file content
return (concat,timestamp)
- concat: concatenation of file content
+ concat: concatenation of file content, read by `reader`
timestamp: max(os.path.getmtime of file_list)
"""
+ if reader is None:
+ def reader(f):
+ with open(f) as fp:
+ return fp.read()
+
files_content = []
files_timestamp = 0
for fname in file_list:
ftime = os.path.getmtime(fname)
if ftime > files_timestamp:
files_timestamp = ftime
- files_content.append(open(fname).read())
+
+ files_content.append(reader(fname))
files_concat = "".join(files_content)
return files_concat,files_timestamp
addons = self.server_wide_modules(req)
else:
addons = addons.split(',')
+ r = []
for addon in addons:
manifest = openerpweb.addons_manifest.get(addon, None)
if not manifest:
globlist = manifest.get(key, [])
for pattern in globlist:
for path in glob.glob(os.path.normpath(os.path.join(addons_path, addon, pattern))):
- yield path, path[len(addons_path):]
+ r.append( (path, path[len(addons_path):]))
+ return r
def manifest_list(self, req, mods, extension):
if not req.debug:
@openerpweb.httprequest
def css(self, req, mods=None):
- files = [f[0] for f in self.manifest_glob(req, mods, 'css')]
- content,timestamp = concat_files(files)
+
+ files = list(self.manifest_glob(req, mods, 'css'))
+ file_map = dict(files)
+
+ rx_import = re.compile(r"""@import\s+('|")(?!'|"|/|https?://)""", re.U)
+ rx_url = re.compile(r"""url\s*\(\s*('|"|)(?!'|"|/|https?://)""", re.U)
+
+
+ def reader(f):
+ """read the a css file and absolutify all relative uris"""
+ with open(f) as fp:
+ data = fp.read()
+
+ web_path = file_map[f]
+ web_dir = os.path.dirname(web_path)
+
+ data = re.sub(
+ rx_import,
+ r"""@import \1%s/""" % (web_dir,),
+ data,
+ )
+
+ data = re.sub(
+ rx_url,
+ r"""url(\1%s/""" % (web_dir,),
+ data,
+ )
+ return data
+
+ content,timestamp = concat_files((f[0] for f in files), reader)
# TODO use timestamp to set Last mofified date and E-tag
return req.make_response(content, [('Content-Type', 'text/css')])
params['db_lang'],
params['create_admin_pwd']
)
-
+
try:
return req.session.proxy("db").create(*create_attrs)
except xmlrpclib.Fault, e:
- if e.faultCode and e.faultCode.split(':')[0] == 'AccessDenied':
- return {'error': e.faultCode, 'title': 'Create Database'}
- return {'error': 'Could not create database !', 'title': 'Create Database'}
+ if e.faultCode and isinstance(e.faultCode, str)\
+ and e.faultCode.split(':')[0] == 'AccessDenied':
+ return {'error': e.faultCode, 'title': 'Database creation error'}
+ return {
+ 'error': "Could not create database '%s': %s" % (
+ params['db_name'], e.faultString),
+ 'title': 'Database creation error'
+ }
@openerpweb.jsonrequest
def drop(self, req, fields):
@openerpweb.httprequest
def restore(self, req, db_file, restore_pwd, new_db):
try:
- data = base64.b64encode(db_file.file.read())
+ data = base64.b64encode(db_file.read())
req.session.proxy("db").restore(restore_pwd, new_db, data)
return ''
except xmlrpclib.Fault, e:
"session_id": req.session_id,
"uid": req.session._uid,
"context": ctx,
- "db": req.session._db
+ "db": req.session._db,
+ "login": req.session._login
}
@openerpweb.jsonrequest
return {
"uid": req.session._uid,
"context": req.session.get_context() if req.session._uid else False,
- "db": req.session._db
+ "db": req.session._db,
+ "login": req.session._login
}
@openerpweb.jsonrequest
# values come from the server, we can just eval them
if isinstance(action.get('context'), basestring):
action['context'] = eval( action['context'], eval_ctx ) or {}
-
+
if isinstance(action.get('domain'), basestring):
action['domain'] = eval( action['domain'], eval_ctx ) or []
else:
:param dict action: an action descriptor
:returns: nothing, the action is modified in place
"""
- if 'views' not in action:
+ if not action.get('views'):
generate_views(action)
+ id_form = None
+ for index, (id, mode) in enumerate(action['views']):
+ if mode == 'form':
+ id_form = id
+ break
+ if id_form is not None:
+ action['views'].insert(index + 1, (id_form, 'page'))
+
if action.pop('view_type', 'form') != 'form':
return action
return Model.unlink(ids, req.session.eval_context(req.context))
def call_common(self, req, model, method, args, domain_id=None, context_id=None):
- domain = args[domain_id] if domain_id and len(args) - 1 >= domain_id else []
- context = args[context_id] if context_id and len(args) - 1 >= context_id else {}
+ has_domain = domain_id is not None and domain_id < len(args)
+ has_context = context_id is not None and context_id < len(args)
+
+ domain = args[domain_id] if has_domain else []
+ context = args[context_id] if has_context else {}
c, d = eval_context_and_domain(req.session, context, domain)
- if domain_id and len(args) - 1 >= domain_id:
+ if has_domain:
args[domain_id] = d
- if context_id and len(args) - 1 >= context_id:
+ if has_context:
args[context_id] = c
for i in xrange(len(args)):
context = req.session.eval_context(req.context)
fvg = Model.fields_view_get(view_id, view_type, context, toolbar, submenu)
# todo fme?: check that we should pass the evaluated context here
- self.process_view(req.session, fvg, context, transform)
+ self.process_view(req.session, fvg, context, transform, (view_type == 'kanban'))
if toolbar and transform:
self.process_toolbar(req, fvg['toolbar'])
return fvg
- def process_view(self, session, fvg, context, transform):
+ def process_view(self, session, fvg, context, transform, preserve_whitespaces=False):
# depending on how it feels, xmlrpclib.ServerProxy can translate
# XML-RPC strings to ``str`` or ``unicode``. ElementTree does not
# enjoy unicode strings which can not be trivially converted to
xml = self.transform_view(arch, session, evaluation_context)
else:
xml = ElementTree.fromstring(arch)
- fvg['arch'] = web.common.xml2json.Xml2Json.convert_element(xml)
+ fvg['arch'] = web.common.xml2json.Xml2Json.convert_element(xml, preserve_whitespaces)
for field in fvg['fields'].itervalues():
if field.get('views'):
domain = elem.get(el, '').strip()
if domain:
elem.set(el, parse_domain(domain, session))
+ elem.set(el + '_string', domain)
for el in ['context', 'default_get']:
context_string = elem.get(el, '').strip()
if context_string:
elem.set(el, parse_context(context_string, session))
+ elem.set(el + '_string', context_string)
@openerpweb.jsonrequest
def load(self, req, model, view_id, view_type, toolbar=False):
}, context)
return to_return
+ @openerpweb.jsonrequest
+ def add_to_dashboard(self, req, menu_id, action_id, context_to_save, domain, view_mode, name=''):
+ ctx = web.common.nonliterals.CompoundContext(context_to_save)
+ ctx.session = req.session
+ ctx = ctx.evaluate()
+ domain = web.common.nonliterals.CompoundDomain(domain)
+ domain.session = req.session
+ domain = domain.evaluate()
+
+ dashboard_action = load_actions_from_ir_values(req, 'action', 'tree_but_open',
+ [('ir.ui.menu', menu_id)], False)
+ if dashboard_action:
+ action = dashboard_action[0][2]
+ if action['res_model'] == 'board.board' and action['views'][0][1] == 'form':
+ # Maybe should check the content instead of model board.board ?
+ view_id = action['views'][0][0]
+ board = req.session.model(action['res_model']).fields_view_get(view_id, 'form')
+ if board and 'arch' in board:
+ xml = ElementTree.fromstring(board['arch'])
+ column = xml.find('./board/column')
+ if column:
+ new_action = ElementTree.Element('action', {
+ 'name' : str(action_id),
+ 'string' : name,
+ 'view_mode' : view_mode,
+ 'context' : str(ctx),
+ 'domain' : str(domain)
+ })
+ column.insert(0, new_action)
+ arch = ElementTree.tostring(xml, 'utf-8')
+ return req.session.model('ir.ui.view.custom').create({
+ 'user_id': req.session._uid,
+ 'ref_id': view_id,
+ 'arch': arch
+ }, req.session.eval_context(req.context))
+
+ return False
+
class Binary(openerpweb.Controller):
_cp_path = "/web/binary"
@openerpweb.jsonrequest
def get_fields(self, req, model, prefix='', parent_name= '',
- import_compat=True, parent_field_type=None):
+ import_compat=True, parent_field_type=None,
+ exclude=None):
if import_compat and parent_field_type == "many2one":
fields = {}
else:
fields = self.fields_get(req, model)
- fields['.id'] = fields.pop('id') if 'id' in fields else {'string': 'ID'}
+
+ if import_compat:
+ fields.pop('id', None)
+ else:
+ fields['.id'] = fields.pop('id', {'string': 'ID'})
fields_sequence = sorted(fields.iteritems(),
key=lambda field: field[1].get('string', ''))
records = []
for field_name, field in fields_sequence:
+ if import_compat and (exclude and field_name in exclude):
+ continue
if import_compat and field.get('readonly'):
# If none of the field's states unsets readonly, skip the field
if all(dict(attrs).get('readonly', True)
record = {'id': id, 'string': name,
'value': id, 'children': False,
'field_type': field.get('type'),
- 'required': field.get('required')}
+ 'required': field.get('required'),
+ 'relation_field': field.get('relation_field')}
records.append(record)
if len(name.split('/')) < 3 and 'relation' in field:
def fields_info(self, req, model, export_fields):
info = {}
fields = self.fields_get(req, model)
- fields['.id'] = fields.pop('id') if 'id' in fields else {'string': 'ID'}
# To make fields retrieval more efficient, fetch all sub-fields of a
# given field at the same time. Because the order in the export list is
context = req.session.eval_context(req.context)
Model = req.session.model(model)
- ids = ids or Model.search(domain, context=context)
+ ids = ids or Model.search(domain, 0, False, False, context)
field_names = map(operator.itemgetter('name'), fields)
import_data = Model.export_data(ids, field_names, context).get('datas',[])
for cell_index, cell_value in enumerate(row):
if isinstance(cell_value, basestring):
cell_value = re.sub("\r", " ", cell_value)
+ if cell_value is False: cell_value = None
worksheet.write(row_index + 1, cell_index, cell_value, style)
fp = StringIO()