{"action":"created","comment":{"url":"https://api.github.com/repos/odoo/odoo/pulls/comments/32757217","id":32757217,"diff_hunk":"@@ -414,31 +414,48 @@ def state_update(self, newstate, states_to_update, level=100):\n \n         return demo\n \n-    def button_install(self, cr, uid, ids, context=None):\n-\n-        # Mark the given modules to be installed.\n-        self.state_update(cr, uid, ids, 'to install', ['uninstalled'], context=context)\n-\n-        # Mark (recursively) the newly satisfied modules to also be installed\n-\n-        # Select all auto-installable (but not yet installed) modules.\n-        domain = [('state', '=', 'uninstalled'), ('auto_install', '=', True)]\n-        uninstalled_ids = self.search(cr, uid, domain, context=context)\n-        uninstalled_modules = self.browse(cr, uid, uninstalled_ids, context=context)\n-\n-        # Keep those with:\n-        #  - all dependencies satisfied (installed or to be installed),\n-        #  - at least one dependency being 'to install'\n-        satisfied_states = frozenset(('installed', 'to install', 'to upgrade'))\n-        def all_depencies_satisfied(m):\n-            states = set(d.state for d in m.dependencies_id)\n-            return states.issubset(satisfied_states) and ('to install' in states)\n-        to_install_modules = filter(all_depencies_satisfied, uninstalled_modules)\n-        to_install_ids = map(lambda m: m.id, to_install_modules)\n-\n-        # Mark them to be installed.\n-        if to_install_ids:\n-            self.button_install(cr, uid, to_install_ids, context=context)\n+    @api.multi\n+    def button_install(self):\n+        # domain to select auto-installable (but not yet installed) modules\n+        auto_domain = [('state', '=', 'uninstalled'), ('auto_install', '=', True)]\n+\n+        # determine whether an auto-install module must be installed:\n+        #  - all its dependencies are installed or to be installed,\n+        #  - at least one dependency is 'to install'\n+        install_states = frozenset(('installed', 'to install', 'to upgrade'))\n+        def must_install(module):\n+            states = set(dep.state for dep in module.dependencies_id)\n+            return states <= install_states and 'to install' in states\n+\n+        modules = self\n+        while modules:\n+            # Mark the given modules and their dependencies to be installed.\n+            modules.state_update('to install', ['uninstalled'])\n+\n+            # Determine which auto-installable modules must be installed.\n+            modules = self.search(auto_domain).filtered(must_install)\n+\n+        # retrieve the installed (or to be installed) theme modules\n+        theme_category = self.env.ref('base.module_category_theme')\n+        theme_modules = self.search([\n+            ('state', 'in', list(install_states)),\n+            ('category_id', 'child_of', [theme_category.id]),\n+        ])\n+\n+        # determine all theme modules that module depends on, including itself\n+        def theme_deps(module):\n+            deps = module.mapped('dependencies_id.depend_id')\n+            return (module & theme_modules) | (deps and deps.mapped(theme_deps))\n+\n+        # check: the installation is valid if all installed theme modules\n+        # correspond to one theme module and all its theme dependencies\n+        if 'to install' in theme_modules.mapped('state') and \\\n+                all(theme_deps(module) != theme_modules for module in theme_modules):\n+            raise UserError(_(\n+                \"You are trying to install non-compatible theme modules:\\n%s\\n\\n\" \\\n+                \"You should first uninstall existing theme modules before installing another theme module.\\n\"\n+                \"Beware that switching themes may have some impact on your website pages!\"\n+            ) % (\", \".join(\"%s (%s)\" % (module.shortdesc, module.name) for module in theme_modules),))","path":"openerp/addons/base/module/module.py","position":70,"original_position":70,"commit_id":"4f0ec5ba0648964df145c196ea36a13e91be63fc","original_commit_id":"4f0ec5ba0648964df145c196ea36a13e91be63fc","user":{"login":"odony","id":2039870,"avatar_url":"https://avatars.githubusercontent.com/u/2039870?v=3","gravatar_id":"","url":"https://api.github.com/users/odony","html_url":"https://github.com/odony","followers_url":"https://api.github.com/users/odony/followers","following_url":"https://api.github.com/users/odony/following{/other_user}","gists_url":"https://api.github.com/users/odony/gists{/gist_id}","starred_url":"https://api.github.com/users/odony/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/odony/subscriptions","organizations_url":"https://api.github.com/users/odony/orgs","repos_url":"https://api.github.com/users/odony/repos","events_url":"https://api.github.com/users/odony/events{/privacy}","received_events_url":"https://api.github.com/users/odony/received_events","type":"User","site_admin":false},"body":"Perhaps we can include the themes as a bullet list, and indicate the state of the theme instead of its technical name, e.g. something like this pseudo-code:\r\n```python\r\nstate_labels = dict(self.fields_get(['state'])['state']['selection'])\r\nthemes_list = [\"\\n- %s (%s)\" % (m.shortdesc, state_labels[m.state]) for m in theme_modules]\r\nraise UserError(_(\r\n    \"You are trying to install incompatible theme modules:\\n%s\\n\\n\" \\\r\n    \"Please uninstall your current theme before installing another one.\\n\"\r\n    \"Warning: switching themes may significantly alter the look of your current website pages!\"\r\n) % (''.join(themes_list),))\r\n```\r\n\r\nWe should probably also modify the warning generated by the uninstall wizard to add this warning about the current website if the user is uninstalling a theme.\r\n\r\nThanks!","created_at":"2015-06-18T17:45:49Z","updated_at":"2015-06-18T17:45:49Z","html_url":"https://github.com/odoo/odoo/pull/7147#discussion_r32757217","pull_request_url":"https://api.github.com/repos/odoo/odoo/pulls/7147","_links":{"self":{"href":"https://api.github.com/repos/odoo/odoo/pulls/comments/32757217"},"html":{"href":"https://github.com/odoo/odoo/pull/7147#discussion_r32757217"},"pull_request":{"href":"https://api.github.com/repos/odoo/odoo/pulls/7147"}}},"pull_request":{"url":"https://api.github.com/repos/odoo/odoo/pulls/7147","id":37992878,"html_url":"https://github.com/odoo/odoo/pull/7147","diff_url":"https://github.com/odoo/odoo/pull/7147.diff","patch_url":"https://github.com/odoo/odoo/pull/7147.patch","issue_url":"https://api.github.com/repos/odoo/odoo/issues/7147","number":7147,"state":"open","locked":false,"title":"[IMP] module: manage installation of theme modules","user":{"login":"rco-odoo","id":7578141,"avatar_url":"https://avatars.githubusercontent.com/u/7578141?v=3","gravatar_id":"","url":"https://api.github.com/users/rco-odoo","html_url":"https://github.com/rco-odoo","followers_url":"https://api.github.com/users/rco-odoo/followers","following_url":"https://api.github.com/users/rco-odoo/following{/other_user}","gists_url":"https://api.github.com/users/rco-odoo/gists{/gist_id}","starred_url":"https://api.github.com/users/rco-odoo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rco-odoo/subscriptions","organizations_url":"https://api.github.com/users/rco-odoo/orgs","repos_url":"https://api.github.com/users/rco-odoo/repos","events_url":"https://api.github.com/users/rco-odoo/events{/privacy}","received_events_url":"https://api.github.com/users/rco-odoo/received_events","type":"User","site_admin":false},"body":"Prevent the installation of a theme module if another incompatible theme module is already installed.\r\nTwo theme modules are considered *compatible* if one of them depends on the other.","created_at":"2015-06-18T10:39:13Z","updated_at":"2015-06-18T17:45:49Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f412dd70f9192251876cfd4e2fdf3a4f8f6992bf","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/odoo/odoo/pulls/7147/commits","review_comments_url":"https://api.github.com/repos/odoo/odoo/pulls/7147/comments","review_comment_url":"https://api.github.com/repos/odoo/odoo/pulls/comments{/number}","comments_url":"https://api.github.com/repos/odoo/odoo/issues/7147/comments","statuses_url":"https://api.github.com/repos/odoo/odoo/statuses/4f0ec5ba0648964df145c196ea36a13e91be63fc","head":{"label":"odoo-dev:saas-6-theme_modules-rco","ref":"saas-6-theme_modules-rco","sha":"4f0ec5ba0648964df145c196ea36a13e91be63fc","user":{"login":"odoo-dev","id":7466976,"avatar_url":"https://avatars.githubusercontent.com/u/7466976?v=3","gravatar_id":"","url":"https://api.github.com/users/odoo-dev","html_url":"https://github.com/odoo-dev","followers_url":"https://api.github.com/users/odoo-dev/followers","following_url":"https://api.github.com/users/odoo-dev/following{/other_user}","gists_url":"https://api.github.com/users/odoo-dev/gists{/gist_id}","starred_url":"https://api.github.com/users/odoo-dev/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/odoo-dev/subscriptions","organizations_url":"https://api.github.com/users/odoo-dev/orgs","repos_url":"https://api.github.com/users/odoo-dev/repos","events_url":"https://api.github.com/users/odoo-dev/events{/privacy}","received_events_url":"https://api.github.com/users/odoo-dev/received_events","type":"Organization","site_admin":false},"repo":{"id":19853934,"name":"odoo","full_name":"odoo-dev/odoo","owner":{"login":"odoo-dev","id":7466976,"avatar_url":"https://avatars.githubusercontent.com/u/7466976?v=3","gravatar_id":"","url":"https://api.github.com/users/odoo-dev","html_url":"https://github.com/odoo-dev","followers_url":"https://api.github.com/users/odoo-dev/followers","following_url":"https://api.github.com/users/odoo-dev/following{/other_user}","gists_url":"https://api.github.com/users/odoo-dev/gists{/gist_id}","starred_url":"https://api.github.com/users/odoo-dev/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/odoo-dev/subscriptions","organizations_url":"https://api.github.com/users/odoo-dev/orgs","repos_url":"https://api.github.com/users/odoo-dev/repos","events_url":"https://api.github.com/users/odoo-dev/events{/privacy}","received_events_url":"https://api.github.com/users/odoo-dev/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/odoo-dev/odoo","description":"RD Dev Repository","fork":true,"url":"https://api.github.com/repos/odoo-dev/odoo","forks_url":"https://api.github.com/repos/odoo-dev/odoo/forks","keys_url":"https://api.github.com/repos/odoo-dev/odoo/keys{/key_id}","collaborators_url":"https://api.github.com/repos/odoo-dev/odoo/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/odoo-dev/odoo/teams","hooks_url":"https://api.github.com/repos/odoo-dev/odoo/hooks","issue_events_url":"https://api.github.com/repos/odoo-dev/odoo/issues/events{/number}","events_url":"https://api.github.com/repos/odoo-dev/odoo/events","assignees_url":"https://api.github.com/repos/odoo-dev/odoo/assignees{/user}","branches_url":"https://api.github.com/repos/odoo-dev/odoo/branches{/branch}","tags_url":"https://api.github.com/repos/odoo-dev/odoo/tags","blobs_url":"https://api.github.com/repos/odoo-dev/odoo/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/odoo-dev/odoo/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/odoo-dev/odoo/git/refs{/sha}","trees_url":"https://api.github.com/repos/odoo-dev/odoo/git/trees{/sha}","statuses_url":"https://api.github.com/repos/odoo-dev/odoo/statuses/{sha}","languages_url":"https://api.github.com/repos/odoo-dev/odoo/languages","stargazers_url":"https://api.github.com/repos/odoo-dev/odoo/stargazers","contributors_url":"https://api.github.com/repos/odoo-dev/odoo/contributors","subscribers_url":"https://api.github.com/repos/odoo-dev/odoo/subscribers","subscription_url":"https://api.github.com/repos/odoo-dev/odoo/subscription","commits_url":"https://api.github.com/repos/odoo-dev/odoo/commits{/sha}","git_commits_url":"https://api.github.com/repos/odoo-dev/odoo/git/commits{/sha}","comments_url":"https://api.github.com/repos/odoo-dev/odoo/comments{/number}","issue_comment_url":"https://api.github.com/repos/odoo-dev/odoo/issues/comments{/number}","contents_url":"https://api.github.com/repos/odoo-dev/odoo/contents/{+path}","compare_url":"https://api.github.com/repos/odoo-dev/odoo/compare/{base}...{head}","merges_url":"https://api.github.com/repos/odoo-dev/odoo/merges","archive_url":"https://api.github.com/repos/odoo-dev/odoo/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/odoo-dev/odoo/downloads","issues_url":"https://api.github.com/repos/odoo-dev/odoo/issues{/number}","pulls_url":"https://api.github.com/repos/odoo-dev/odoo/pulls{/number}","milestones_url":"https://api.github.com/repos/odoo-dev/odoo/milestones{/number}","notifications_url":"https://api.github.com/repos/odoo-dev/odoo/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/odoo-dev/odoo/labels{/name}","releases_url":"https://api.github.com/repos/odoo-dev/odoo/releases{/id}","created_at":"2014-05-16T11:16:19Z","updated_at":"2015-06-17T11:07:18Z","pushed_at":"2015-06-18T16:48:01Z","git_url":"git://github.com/odoo-dev/odoo.git","ssh_url":"git@github.com:odoo-dev/odoo.git","clone_url":"https://github.com/odoo-dev/odoo.git","svn_url":"https://github.com/odoo-dev/odoo","homepage":"https://www.odoo.com","size":1185721,"stargazers_count":57,"watchers_count":57,"language":null,"has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":20,"mirror_url":null,"open_issues_count":0,"forks":20,"open_issues":0,"watchers":57,"default_branch":"master"}},"base":{"label":"odoo:saas-6","ref":"saas-6","sha":"1b7c49bf1e0843c1d11c856ef5474ebfc2c261d1","user":{"login":"odoo","id":6368483,"avatar_url":"https://avatars.githubusercontent.com/u/6368483?v=3","gravatar_id":"","url":"https://api.github.com/users/odoo","html_url":"https://github.com/odoo","followers_url":"https://api.github.com/users/odoo/followers","following_url":"https://api.github.com/users/odoo/following{/other_user}","gists_url":"https://api.github.com/users/odoo/gists{/gist_id}","starred_url":"https://api.github.com/users/odoo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/odoo/subscriptions","organizations_url":"https://api.github.com/users/odoo/orgs","repos_url":"https://api.github.com/users/odoo/repos","events_url":"https://api.github.com/users/odoo/events{/privacy}","received_events_url":"https://api.github.com/users/odoo/received_events","type":"Organization","site_admin":false},"repo":{"id":19745004,"name":"odoo","full_name":"odoo/odoo","owner":{"login":"odoo","id":6368483,"avatar_url":"https://avatars.githubusercontent.com/u/6368483?v=3","gravatar_id":"","url":"https://api.github.com/users/odoo","html_url":"https://github.com/odoo","followers_url":"https://api.github.com/users/odoo/followers","following_url":"https://api.github.com/users/odoo/following{/other_user}","gists_url":"https://api.github.com/users/odoo/gists{/gist_id}","starred_url":"https://api.github.com/users/odoo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/odoo/subscriptions","organizations_url":"https://api.github.com/users/odoo/orgs","repos_url":"https://api.github.com/users/odoo/repos","events_url":"https://api.github.com/users/odoo/events{/privacy}","received_events_url":"https://api.github.com/users/odoo/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/odoo/odoo","description":"Odoo (formerly OpenERP). Open Source Apps To Grow Your Business.","fork":false,"url":"https://api.github.com/repos/odoo/odoo","forks_url":"https://api.github.com/repos/odoo/odoo/forks","keys_url":"https://api.github.com/repos/odoo/odoo/keys{/key_id}","collaborators_url":"https://api.github.com/repos/odoo/odoo/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/odoo/odoo/teams","hooks_url":"https://api.github.com/repos/odoo/odoo/hooks","issue_events_url":"https://api.github.com/repos/odoo/odoo/issues/events{/number}","events_url":"https://api.github.com/repos/odoo/odoo/events","assignees_url":"https://api.github.com/repos/odoo/odoo/assignees{/user}","branches_url":"https://api.github.com/repos/odoo/odoo/branches{/branch}","tags_url":"https://api.github.com/repos/odoo/odoo/tags","blobs_url":"https://api.github.com/repos/odoo/odoo/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/odoo/odoo/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/odoo/odoo/git/refs{/sha}","trees_url":"https://api.github.com/repos/odoo/odoo/git/trees{/sha}","statuses_url":"https://api.github.com/repos/odoo/odoo/statuses/{sha}","languages_url":"https://api.github.com/repos/odoo/odoo/languages","stargazers_url":"https://api.github.com/repos/odoo/odoo/stargazers","contributors_url":"https://api.github.com/repos/odoo/odoo/contributors","subscribers_url":"https://api.github.com/repos/odoo/odoo/subscribers","subscription_url":"https://api.github.com/repos/odoo/odoo/subscription","commits_url":"https://api.github.com/repos/odoo/odoo/commits{/sha}","git_commits_url":"https://api.github.com/repos/odoo/odoo/git/commits{/sha}","comments_url":"https://api.github.com/repos/odoo/odoo/comments{/number}","issue_comment_url":"https://api.github.com/repos/odoo/odoo/issues/comments{/number}","contents_url":"https://api.github.com/repos/odoo/odoo/contents/{+path}","compare_url":"https://api.github.com/repos/odoo/odoo/compare/{base}...{head}","merges_url":"https://api.github.com/repos/odoo/odoo/merges","archive_url":"https://api.github.com/repos/odoo/odoo/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/odoo/odoo/downloads","issues_url":"https://api.github.com/repos/odoo/odoo/issues{/number}","pulls_url":"https://api.github.com/repos/odoo/odoo/pulls{/number}","milestones_url":"https://api.github.com/repos/odoo/odoo/milestones{/number}","notifications_url":"https://api.github.com/repos/odoo/odoo/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/odoo/odoo/labels{/name}","releases_url":"https://api.github.com/repos/odoo/odoo/releases{/id}","created_at":"2014-05-13T15:38:58Z","updated_at":"2015-06-18T15:46:52Z","pushed_at":"2015-06-18T17:41:53Z","git_url":"git://github.com/odoo/odoo.git","ssh_url":"git@github.com:odoo/odoo.git","clone_url":"https://github.com/odoo/odoo.git","svn_url":"https://github.com/odoo/odoo","homepage":"https://www.odoo.com","size":1287454,"stargazers_count":2674,"watchers_count":2674,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2219,"mirror_url":null,"open_issues_count":2445,"forks":2219,"open_issues":2445,"watchers":2674,"default_branch":"8.0"}},"_links":{"self":{"href":"https://api.github.com/repos/odoo/odoo/pulls/7147"},"html":{"href":"https://github.com/odoo/odoo/pull/7147"},"issue":{"href":"https://api.github.com/repos/odoo/odoo/issues/7147"},"comments":{"href":"https://api.github.com/repos/odoo/odoo/issues/7147/comments"},"review_comments":{"href":"https://api.github.com/repos/odoo/odoo/pulls/7147/comments"},"review_comment":{"href":"https://api.github.com/repos/odoo/odoo/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/odoo/odoo/pulls/7147/commits"},"statuses":{"href":"https://api.github.com/repos/odoo/odoo/statuses/4f0ec5ba0648964df145c196ea36a13e91be63fc"}}}}