~therp-nl/openerp-web/7.0-lp1013636-x2m_honour_required_attribute

« back to all changes in this revision

Viewing changes to addons/web/controllers/main.py

[MERGE] from trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
410
410
        return {"db_list": dbs}
411
411
 
412
412
    @openerpweb.jsonrequest
413
 
    def progress(self, req, password, id):
414
 
        return req.session.proxy('db').get_progress(password, id)
415
 
 
416
 
    @openerpweb.jsonrequest
417
413
    def create(self, req, fields):
418
 
 
419
414
        params = dict(map(operator.itemgetter('name', 'value'), fields))
420
415
        create_attrs = (
421
416
            params['super_admin_pwd'],
425
420
            params['create_admin_pwd']
426
421
        )
427
422
 
428
 
        try:
429
 
            return req.session.proxy("db").create(*create_attrs)
430
 
        except xmlrpclib.Fault, e:
431
 
            if e.faultCode and isinstance(e.faultCode, str)\
432
 
                and e.faultCode.split(':')[0] == 'AccessDenied':
433
 
                    return {'error': e.faultCode, 'title': 'Database creation error'}
434
 
            return {
435
 
                'error': "Could not create database '%s': %s" % (
436
 
                    params['db_name'], e.faultString),
437
 
                'title': 'Database creation error'
438
 
            }
 
423
        return req.session.proxy("db").create_database(*create_attrs)
439
424
 
440
425
    @openerpweb.jsonrequest
441
426
    def drop(self, req, fields):
487
472
                return {'error': e.faultCode, 'title': 'Change Password'}
488
473
        return {'error': 'Error, password not changed !', 'title': 'Change Password'}
489
474
 
 
475
def topological_sort(modules):
 
476
    """ Return a list of module names sorted so that their dependencies of the
 
477
    modules are listed before the module itself
 
478
 
 
479
    modules is a dict of {module_name: dependencies}
 
480
 
 
481
    :param modules: modules to sort
 
482
    :type modules: dict
 
483
    :returns: list(str)
 
484
    """
 
485
 
 
486
    dependencies = set(itertools.chain.from_iterable(modules.itervalues()))
 
487
    # incoming edge: dependency on other module (if a depends on b, a has an
 
488
    # incoming edge from b, aka there's an edge from b to a)
 
489
    # outgoing edge: other module depending on this one
 
490
 
 
491
    # [Tarjan 1976], http://en.wikipedia.org/wiki/Topological_sorting#Algorithms
 
492
    #L ← Empty list that will contain the sorted nodes
 
493
    L = []
 
494
    #S ← Set of all nodes with no outgoing edges (modules on which no other
 
495
    #    module depends)
 
496
    S = set(module for module in modules if module not in dependencies)
 
497
 
 
498
    visited = set()
 
499
    #function visit(node n)
 
500
    def visit(n):
 
501
        #if n has not been visited yet then
 
502
        if n not in visited:
 
503
            #mark n as visited
 
504
            visited.add(n)
 
505
            #change: n not web module, can not be resolved, ignore
 
506
            if n not in modules: return
 
507
            #for each node m with an edge from m to n do (dependencies of n)
 
508
            for m in modules[n]:
 
509
                #visit(m)
 
510
                visit(m)
 
511
            #add n to L
 
512
            L.append(n)
 
513
    #for each node n in S do
 
514
    for n in S:
 
515
        #visit(n)
 
516
        visit(n)
 
517
    return L
 
518
 
490
519
class Session(openerpweb.Controller):
491
520
    _cp_path = "/web/session"
492
521
 
554
583
    def modules(self, req):
555
584
        # Compute available candidates module
556
585
        loadable = openerpweb.addons_manifest
557
 
        loaded = req.config.server_wide_modules
 
586
        loaded = set(req.config.server_wide_modules)
558
587
        candidates = [mod for mod in loadable if mod not in loaded]
559
588
 
560
 
        # Compute active true modules that might be on the web side only
561
 
        active = set(name for name in candidates
562
 
                     if openerpweb.addons_manifest[name].get('active'))
 
589
        # already installed modules have no dependencies
 
590
        modules = dict.fromkeys(loaded, [])
 
591
 
 
592
        # Compute auto_install modules that might be on the web side only
 
593
        modules.update((name, openerpweb.addons_manifest[name].get('depends', []))
 
594
                      for name in candidates
 
595
                      if openerpweb.addons_manifest[name].get('auto_install'))
563
596
 
564
597
        # Retrieve database installed modules
565
598
        Modules = req.session.model('ir.module.module')
566
 
        installed = set(module['name'] for module in Modules.search_read(
567
 
            [('state','=','installed'), ('name','in', candidates)], ['name']))
 
599
        for module in Modules.search_read(
 
600
                        [('state','=','installed'), ('name','in', candidates)],
 
601
                        ['name', 'dependencies_id']):
 
602
            deps = module.get('dependencies_id')
 
603
            if deps:
 
604
                dependencies = map(
 
605
                    operator.itemgetter('name'),
 
606
                    req.session.model('ir.module.module.dependency').read(deps, ['name']))
 
607
                modules[module['name']] = list(
 
608
                    set(modules.get(module['name'], []) + dependencies))
568
609
 
569
 
        # Merge both
570
 
        return list(active | installed)
 
610
        sorted_modules = topological_sort(modules)
 
611
        return [module for module in sorted_modules if module not in loaded]
571
612
 
572
613
    @openerpweb.jsonrequest
573
614
    def eval_domain_and_context(self, req, contexts, domains,
1304
1345
        filters = Model.get_filters(model)
1305
1346
        for filter in filters:
1306
1347
            try:
1307
 
                filter["context"] = req.session.eval_context(
1308
 
                    parse_context(filter["context"], req.session))
1309
 
                filter["domain"] = req.session.eval_domain(
1310
 
                    parse_domain(filter["domain"], req.session))
 
1348
                parsed_context = parse_context(filter["context"], req.session)
 
1349
                filter["context"] = (parsed_context
 
1350
                        if not isinstance(parsed_context, common.nonliterals.BaseContext)
 
1351
                        else req.session.eval_context(parsed_context))
 
1352
 
 
1353
                parsed_domain = parse_domain(filter["domain"], req.session)
 
1354
                filter["domain"] = (parsed_domain
 
1355
                        if not isinstance(parsed_domain, common.nonliterals.BaseDomain)
 
1356
                        else req.session.eval_domain(parsed_domain))
1311
1357
            except Exception:
1312
1358
                logger.exception("Failed to parse custom filter %s in %s",
1313
1359
                                 filter['name'], model)
1340
1386
        ctx = common.nonliterals.CompoundContext(context_to_save)
1341
1387
        ctx.session = req.session
1342
1388
        ctx = ctx.evaluate()
 
1389
        ctx['dashboard_merge_domains_contexts'] = False # TODO: replace this 6.1 workaround by attribute on <action/>
1343
1390
        domain = common.nonliterals.CompoundDomain(domain)
1344
1391
        domain.session = req.session
1345
1392
        domain = domain.evaluate()
1355
1402
                if board and 'arch' in board:
1356
1403
                    xml = ElementTree.fromstring(board['arch'])
1357
1404
                    column = xml.find('./board/column')
1358
 
                    if column:
 
1405
                    if column is not None:
1359
1406
                        new_action = ElementTree.Element('action', {
1360
1407
                                'name' : str(action_id),
1361
1408
                                'string' : name,