From fbbdef1e9cbbec0d9730fed5476e719b4cad27e0 Mon Sep 17 00:00:00 2001 From: niraj gautam Date: Tue, 5 Sep 2023 11:15:27 +0530 Subject: [PATCH] feat: Dynamically generate license text (#22299) * feat: Add dynamic license dtext * feat: Validate license name * fix(DX): Pass options as click.Choice --------- Co-authored-by: Ankush Menat --- frappe/tests/test_boilerplate.py | 8 ++++---- frappe/utils/boilerplate.py | 32 ++++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/frappe/tests/test_boilerplate.py b/frappe/tests/test_boilerplate.py index a29052bf01..c46a6584c4 100644 --- a/frappe/tests/test_boilerplate.py +++ b/frappe/tests/test_boilerplate.py @@ -32,7 +32,7 @@ class TestBoilerPlate(unittest.TestCase): "app_description": "This app's description contains 'single quotes' and \"double quotes\".", "app_publisher": "Test Publisher", "app_email": "example@example.org", - "app_license": "MIT", + "app_license": "mit", "create_github_workflow": False, } ) @@ -45,7 +45,7 @@ class TestBoilerPlate(unittest.TestCase): "email": "example@example.org", "icon": "", # empty -> default "color": "", - "app_license": "MIT", + "app_license": "mit", "github_workflow": "n", } ) @@ -126,7 +126,7 @@ class TestBoilerPlate(unittest.TestCase): "app_description": "This app's description contains 'single quotes' and \"double quotes\".", "app_publisher": "Test Publisher", "app_email": "example@example.org", - "app_license": "MIT", + "app_license": "mit", } ) @@ -160,7 +160,7 @@ class TestBoilerPlate(unittest.TestCase): "app_description": "This app's description contains 'single quotes' and \"double quotes\".", "app_publisher": "Test Publisher", "app_email": "example@example.org", - "app_license": "MIT", + "app_license": "mit", } ) self.create_app(hooks, no_git=True) diff --git a/frappe/utils/boilerplate.py b/frappe/utils/boilerplate.py index 3522934ec0..85bf3d6f8c 100644 --- a/frappe/utils/boilerplate.py +++ b/frappe/utils/boilerplate.py @@ -11,9 +11,9 @@ import textwrap import click import git +import requests import frappe -from frappe.utils import touch_file APP_TITLE_PATTERN = re.compile(r"^(?![\W])[^\d_\s][\w -]+$", flags=re.UNICODE) @@ -46,7 +46,11 @@ def _get_user_inputs(app_name): "app_description": {"prompt": "App Description"}, "app_publisher": {"prompt": "App Publisher"}, "app_email": {"prompt": "App Email", "validator": is_valid_email}, - "app_license": {"prompt": "App License", "default": "MIT"}, + "app_license": { + "prompt": "App License", + "default": "mit", + "type": click.Choice(get_license_options()), + }, "create_github_workflow": { "prompt": "Create GitHub Workflow action for unittests", "default": False, @@ -92,6 +96,26 @@ def is_valid_title(title) -> bool: return True +def get_license_options() -> list[str]: + url = "https://api.github.com/licenses" + res = requests.get(url=url) + if res.status_code == 200: + res = res.json() + ids = [r.get("spdx_id") for r in res] + return [licencse.lower() for licencse in ids] + + return ["agpl-3.0", "gpl-3.0", "mit", "custom"] + + +def get_license_text(license_name: str) -> str: + url = f"https://api.github.com/licenses/{license_name.lower()}" + res = requests.get(url=url) + if res.status_code == 200: + res = res.json() + return res.get("body") + return license_name + + def _create_app_boilerplate(dest, hooks, no_git=False): frappe.create_folder( os.path.join(dest, hooks.app_name, hooks.app_name, frappe.scrub(hooks.app_title)), @@ -128,9 +152,9 @@ def _create_app_boilerplate(dest, hooks, no_git=False): ) ) ) - + license_body = get_license_text(license_name=hooks.app_license) with open(os.path.join(dest, hooks.app_name, "license.txt"), "w") as f: - f.write(frappe.as_unicode("License: " + hooks.app_license)) + f.write(frappe.as_unicode(license_body)) with open(os.path.join(dest, hooks.app_name, hooks.app_name, "modules.txt"), "w") as f: f.write(frappe.as_unicode(hooks.app_title))