From 0cf86cf082b79371f15ad74e4731df131901d7fa Mon Sep 17 00:00:00 2001 From: Patrick Elmer Date: Sat, 21 Mar 2026 14:32:05 +0100 Subject: [PATCH 1/4] Detect license expression in CLI --- magicli.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/magicli.py b/magicli.py index 20d2e36..e4a746c 100644 --- a/magicli.py +++ b/magicli.py @@ -287,6 +287,20 @@ def get_description(name): return " ".join(stripped for line in doc.splitlines() if (stripped := line.strip())) +def get_license_expression(content): + return { + "Apache License": "Apache-2.0", + "BSD 2-Clause License": "BSD-2-Clause", + "BSD 3-Clause License": "BSD-3-Clause", + "GNU AFFERO GENERAL PUBLIC LICENSE": "AGPL-3.0-or-later", + "GNU GENERAL PUBLIC LICENSE": "GPL-3.0-or-later", + "GNU LESSER GENERAL PUBLIC LICENSE": "LGPL-3.0-or-later", + "MIT License": "MIT", + "Mozilla Public License Version 2.0": "MPL-2.0", + "Public domain statement": "Unlicense", + }.get(content.split("\n")[0].strip()) + + def cli(name="", author="", email="", description="", homepage=""): """ magiCLI✨ @@ -331,6 +345,8 @@ def cli(name="", author="", email="", description="", homepage=""): project.append('readme = "README.md"') if Path("LICENSE").exists(): + if license_expression := get_license_expression(Path("LICENSE").read_text()): + project.append(f'license = "{license_expression}"') project.append('license-files = ["LICENSE"]') if description or (description := get_description(name)): From f78e6bfa8bc4e9cdc30c4cafb7e662f26cc8f85f Mon Sep 17 00:00:00 2001 From: Patrick Elmer Date: Sat, 21 Mar 2026 14:32:47 +0100 Subject: [PATCH 2/4] Add tests for license expression --- tests/fixtures.py | 7 +++++++ tests/test_cli.py | 24 +++++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/tests/fixtures.py b/tests/fixtures.py index b526fe3..3ef34bf 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -30,6 +30,13 @@ def with_tempdir(): _teardown(directory, cwd) +@pytest.fixture +def with_license(): + directory, cwd = _setup(["LICENSE"]) + yield directory.name + _teardown(directory, cwd) + + @pytest.fixture def with_readme_and_license(): directory, cwd = _setup(["README.md", "LICENSE"]) diff --git a/tests/test_cli.py b/tests/test_cli.py index 6e82c3d..a98710d 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -6,12 +6,20 @@ empty_directory, pyproject, with_git, + with_license, with_readme_and_license, with_tempdir, with_two_files, ) -from magicli import cli, get_description, get_homepage, get_output, get_project_name +from magicli import ( + cli, + get_description, + get_homepage, + get_license_expression, + get_output, + get_project_name, +) def module(name): @@ -92,6 +100,20 @@ def test_get_description(): assert get_description("magicli") is not None +def test_get_license_expression(): + assert get_license_expression("Apache License") == "Apache-2.0" + assert get_license_expression(" GNU GENERAL PUBLIC LICENSE ") == "GPL-3.0-or-later" + assert get_license_expression("") == None + + +def test_cli_with_license(with_license): + Path(with_license, "LICENSE").write_text("MIT License") + cli(name="name", author="Patrick Elmer", email="patrick@elmer.ws") + pyproject = Path("pyproject.toml").read_text() + assert 'license = "MIT"' in pyproject + assert 'license-files = ["LICENSE"]' in pyproject + + def test_cli_with_kwargs(with_readme_and_license): cli( name="name", From 9bd9f7847badd228bb885a5a6b876919d3e7f30e Mon Sep 17 00:00:00 2001 From: Patrick Elmer Date: Sat, 21 Mar 2026 14:36:26 +0100 Subject: [PATCH 3/4] Lint code --- magicli.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/magicli.py b/magicli.py index e4a746c..fc69ae0 100644 --- a/magicli.py +++ b/magicli.py @@ -288,6 +288,7 @@ def get_description(name): def get_license_expression(content): + """Returns the license expression used in pyproject.toml.""" return { "Apache License": "Apache-2.0", "BSD 2-Clause License": "BSD-2-Clause", @@ -345,7 +346,8 @@ def cli(name="", author="", email="", description="", homepage=""): project.append('readme = "README.md"') if Path("LICENSE").exists(): - if license_expression := get_license_expression(Path("LICENSE").read_text()): + license_content = Path("LICENSE").read_text(encoding="utf-8") + if license_expression := get_license_expression(license_content): project.append(f'license = "{license_expression}"') project.append('license-files = ["LICENSE"]') From 9f11f8227c7a004b8c7b074ebb5fbc29ca47fab4 Mon Sep 17 00:00:00 2001 From: Patrick Elmer Date: Sun, 22 Mar 2026 11:20:22 +0100 Subject: [PATCH 4/4] Add message for unknown license --- magicli.py | 2 ++ tests/test_cli.py | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/magicli.py b/magicli.py index fc69ae0..4653222 100644 --- a/magicli.py +++ b/magicli.py @@ -349,6 +349,8 @@ def cli(name="", author="", email="", description="", homepage=""): license_content = Path("LICENSE").read_text(encoding="utf-8") if license_expression := get_license_expression(license_content): project.append(f'license = "{license_expression}"') + else: + print("Unknown license: Failed to add SPDX identifier to project.license") project.append('license-files = ["LICENSE"]') if description or (description := get_description(name)): diff --git a/tests/test_cli.py b/tests/test_cli.py index a98710d..89619e4 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -114,7 +114,7 @@ def test_cli_with_license(with_license): assert 'license-files = ["LICENSE"]' in pyproject -def test_cli_with_kwargs(with_readme_and_license): +def test_cli_with_kwargs(capsys, with_readme_and_license): cli( name="name", author="Patrick Elmer", @@ -122,6 +122,8 @@ def test_cli_with_kwargs(with_readme_and_license): description="docstring", homepage="https://github.com/PatrickElmer/magicli", ) + out, _ = capsys.readouterr() + assert "Unknown license" in out assert ( Path("pyproject.toml").read_text() == """\