From d19973a357bdb942caf523cdfadefc4510bbe3dc Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Fri, 9 Oct 2020 11:27:18 +0530 Subject: [PATCH 1/6] fix: Support for multi-site list-apps summary --- frappe/commands/site.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/frappe/commands/site.py b/frappe/commands/site.py index 1f4642658f..d4fcaba3b5 100755 --- a/frappe/commands/site.py +++ b/frappe/commands/site.py @@ -226,11 +226,26 @@ def install_app(context, apps): @pass_context def list_apps(context): "List apps in site" - site = get_site(context) - frappe.init(site=site) - frappe.connect() - print("\n".join(frappe.get_installed_apps())) - frappe.destroy() + import click + titled = False + + if len(context.sites) > 1: + titled = True + + for site in context.sites: + frappe.init(site=site) + frappe.connect() + apps = sorted(frappe.get_installed_apps()) + + if titled: + summary = "{}{}".format(click.style(site + ": ", fg="green"), ", ".join(apps)) + else: + summary = "\n".join(apps) + + if apps and summary.strip(): + print(summary) + + frappe.destroy() @click.command('add-system-manager') @click.argument('email') From 5c5703b8f68c2a76e000f4712a5e60fa501fba57 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Fri, 9 Oct 2020 11:31:18 +0530 Subject: [PATCH 2/6] feat: Show apps excluding frappe using --only-apps --- frappe/commands/site.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frappe/commands/site.py b/frappe/commands/site.py index d4fcaba3b5..189d6eedd4 100755 --- a/frappe/commands/site.py +++ b/frappe/commands/site.py @@ -223,8 +223,9 @@ def install_app(context, apps): @click.command('list-apps') +@click.option('--only-apps', is_flag=True) @pass_context -def list_apps(context): +def list_apps(context, only_apps): "List apps in site" import click titled = False @@ -237,6 +238,9 @@ def list_apps(context): frappe.connect() apps = sorted(frappe.get_installed_apps()) + if only_apps: + apps.remove("frappe") + if titled: summary = "{}{}".format(click.style(site + ": ", fg="green"), ", ".join(apps)) else: From 9cedd7616d10eb41b45b3d53df3fc948bf19980b Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Mon, 9 Nov 2020 12:48:54 +0530 Subject: [PATCH 3/6] refactor: Show versions from Installed Applications to show "real" versions synced with the site database --- frappe/commands/site.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/frappe/commands/site.py b/frappe/commands/site.py index 142cb9f90f..033165e760 100755 --- a/frappe/commands/site.py +++ b/frappe/commands/site.py @@ -223,30 +223,31 @@ def install_app(context, apps): @click.command('list-apps') -@click.option('--only-apps', is_flag=True) @pass_context -def list_apps(context, only_apps): +def list_apps(context): "List apps in site" - import click - titled = False - - if len(context.sites) > 1: - titled = True for site in context.sites: frappe.init(site=site) frappe.connect() - apps = sorted(frappe.get_installed_apps()) + site_title = click.style(f"{site}", fg="green") if len(context.sites) > 1 else "" + apps = frappe.get_single("Installed Applications").installed_applications - if only_apps: - apps.remove("frappe") + if apps: + name_len, ver_len, branch_len = [ + max([len(x.get(y)) for x in apps]) for y in ["app_name", "app_version", "git_branch"] + ] + template = "{{0:{0}}} {{1:{1}}} {{2}}".format(name_len, ver_len, branch_len) + + installed_applications = [template.format(app.app_name, app.app_version, app.git_branch) for app in apps] + applications_summary = "\n".join(installed_applications) + summary = f"\n{site_title}\n{applications_summary}".strip() - if titled: - summary = "{}{}".format(click.style(site + ": ", fg="green"), ", ".join(apps)) else: - summary = "\n".join(apps) + applications_summary = "\n".join(frappe.get_installed_apps()) + summary = f"\n{site_title}\n{applications_summary}".strip() - if apps and summary.strip(): + if applications_summary and summary: print(summary) frappe.destroy() From 6c28f0cffef3ab73631f4fda949e4c28d8a6aa35 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Mon, 9 Nov 2020 13:20:38 +0530 Subject: [PATCH 4/6] style: Sider + Black --- frappe/commands/site.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/frappe/commands/site.py b/frappe/commands/site.py index 033165e760..2c52bddf8f 100755 --- a/frappe/commands/site.py +++ b/frappe/commands/site.py @@ -222,7 +222,7 @@ def install_app(context, apps): sys.exit(exit_code) -@click.command('list-apps') +@click.command("list-apps") @pass_context def list_apps(context): "List apps in site" @@ -230,16 +230,22 @@ def list_apps(context): for site in context.sites: frappe.init(site=site) frappe.connect() - site_title = click.style(f"{site}", fg="green") if len(context.sites) > 1 else "" + site_title = ( + click.style(f"{site}", fg="green") if len(context.sites) > 1 else "" + ) apps = frappe.get_single("Installed Applications").installed_applications if apps: - name_len, ver_len, branch_len = [ - max([len(x.get(y)) for x in apps]) for y in ["app_name", "app_version", "git_branch"] + name_len, ver_len = [ + max([len(x.get(y)) for x in apps]) + for y in ["app_name", "app_version"] ] - template = "{{0:{0}}} {{1:{1}}} {{2}}".format(name_len, ver_len, branch_len) + template = "{{0:{0}}} {{1:{1}}} {{2}}".format(name_len, ver_len) - installed_applications = [template.format(app.app_name, app.app_version, app.git_branch) for app in apps] + installed_applications = [ + template.format(app.app_name, app.app_version, app.git_branch) + for app in apps + ] applications_summary = "\n".join(installed_applications) summary = f"\n{site_title}\n{applications_summary}".strip() @@ -252,6 +258,7 @@ def list_apps(context): frappe.destroy() + @click.command('add-system-manager') @click.argument('email') @click.option('--first-name') From 61b0ffc14dd1012f9b5be1f96a7031c774027684 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Mon, 9 Nov 2020 13:48:06 +0530 Subject: [PATCH 5/6] fix: Add new-lines between sites' summaries --- frappe/commands/site.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/frappe/commands/site.py b/frappe/commands/site.py index 2c52bddf8f..b08030e56a 100755 --- a/frappe/commands/site.py +++ b/frappe/commands/site.py @@ -227,6 +227,13 @@ def install_app(context, apps): def list_apps(context): "List apps in site" + def fix_whitespaces(text): + if site == context.sites[-1]: + text = text.rstrip() + if len(context.sites) == 1: + text = text.lstrip() + return text + for site in context.sites: frappe.init(site=site) frappe.connect() @@ -247,11 +254,13 @@ def list_apps(context): for app in apps ] applications_summary = "\n".join(installed_applications) - summary = f"\n{site_title}\n{applications_summary}".strip() + summary = f"{site_title}\n{applications_summary}\n" else: applications_summary = "\n".join(frappe.get_installed_apps()) - summary = f"\n{site_title}\n{applications_summary}".strip() + summary = f"{site_title}\n{applications_summary}\n" + + summary = fix_whitespaces(summary) if applications_summary and summary: print(summary) From 7394427df001bc8ca1712cd58d12372e737dcb70 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Mon, 9 Nov 2020 15:14:33 +0530 Subject: [PATCH 6/6] test: Add tests for bench list-apps --- frappe/tests/test_commands.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/frappe/tests/test_commands.py b/frappe/tests/test_commands.py index 4e02de795a..9757a823a6 100644 --- a/frappe/tests/test_commands.py +++ b/frappe/tests/test_commands.py @@ -143,5 +143,24 @@ class TestCommands(BaseTestCommands): # test 1: remove app from installed_apps global default self.execute("bench --site {site} remove-from-installed-apps {app}", {"app": app}) + self.assertEquals(self.returncode, 0) self.execute("bench --site {site} list-apps") self.assertNotIn(app, self.stdout) + + def test_list_apps(self): + # test 1: sanity check for command + self.execute("bench --site all list-apps") + self.assertEquals(self.returncode, 0) + + # test 2: bare functionality for single site + self.execute("bench --site {site} list-apps") + self.assertEquals(self.returncode, 0) + list_apps = set([ + _x.split()[0] for _x in self.stdout.split("\n") + ]) + doctype = frappe.get_single("Installed Applications").installed_applications + if doctype: + installed_apps = set([x.app_name for x in doctype]) + else: + installed_apps = set(frappe.get_installed_apps()) + self.assertSetEqual(list_apps, installed_apps)