diff --git a/changes/2309.feature.rst b/changes/2309.feature.rst new file mode 100644 index 000000000..c00f8df2d --- /dev/null +++ b/changes/2309.feature.rst @@ -0,0 +1 @@ +Briefcase now supports license files with names "LICENCE", "LICENSE" and "COPYING" with the extensions ".rst", ".md" and ".txt". diff --git a/src/briefcase/commands/convert.py b/src/briefcase/commands/convert.py index 0a61ab8d5..5ddd06257 100644 --- a/src/briefcase/commands/convert.py +++ b/src/briefcase/commands/convert.py @@ -664,9 +664,8 @@ def migrate_necessary_files(self, project_dir, test_source_dir, module_name): self.merge_or_copy_pyproject(project_dir / "pyproject.toml") # Copy license file if not already there - license_file = self.pep621_data.get("license", {}).get("file") - - if license_file is None and not (self.base_path / "LICENSE").exists(): + license = find_license_filename() + if license is None: self.console.warning( f"\nLicense file not found in '{self.base_path}'. " "Briefcase will create a template 'LICENSE' file." @@ -822,3 +821,27 @@ def find_changelog_filename(base_path): if changelog.is_file(): return format return None + + +def find_license_filename(base_path): + """Find a valid license file in a given directory. + + :param base_Path: The directory to search + :returns: The filename of a license if one is found. Else none if no such + license could be found. + """ + # Collect all possible license file formats. + license_formats = [ + f"{name}{extension}" + for name in ["LICENSE", "LICENCE", "COPYING"] + for extension in ["", ".md", ".rst", ".txt"] + ] + + # If a particular format is found, it returns it as the license. + for file_format in license_formats: + license = base_path / file_format + if license.is_file(): + return file_format + + # Else, no such license exists and return None. + return None diff --git a/src/briefcase/platforms/linux/system.py b/src/briefcase/platforms/linux/system.py index 3804cc042..81cf56057 100644 --- a/src/briefcase/platforms/linux/system.py +++ b/src/briefcase/platforms/linux/system.py @@ -15,7 +15,7 @@ RunCommand, UpdateCommand, ) -from briefcase.commands.convert import find_changelog_filename +from briefcase.commands.convert import find_changelog_filename, find_license_filename from briefcase.config import AppConfig, merge_config from briefcase.exceptions import BriefcaseCommandError, UnsupportedHostError from briefcase.integrations.docker import Docker, DockerAppContext @@ -736,7 +736,7 @@ def build_app(self, app: AppConfig, **kwargs): with self.console.wait_bar("Installing license..."): if license_file := app.license.get("file"): - license_file = self.base_path / license_file + license_file = find_license_filename() if license_file.is_file(): self.tools.shutil.copy(license_file, doc_folder / "copyright") else: @@ -764,7 +764,7 @@ def build_app(self, app: AppConfig, **kwargs): """\ Your project does not contain a LICENSE definition. -Create a file named `LICENSE` in the same directory as your `pyproject.toml` +Create a file named `LICENSE`, `LICENCE` or `COPYING` in the same directory as your `pyproject.toml` with your app's licensing terms, and set `license.file = 'LICENSE'` in your app's configuration. """ diff --git a/tests/commands/convert/test_find_license_filename.py b/tests/commands/convert/test_find_license_filename.py new file mode 100644 index 000000000..0888df547 --- /dev/null +++ b/tests/commands/convert/test_find_license_filename.py @@ -0,0 +1,42 @@ +import pytest + +from briefcase.platforms.linux.system import find_license_filename + +from ...utils import create_file + + +def test_no_license(tmp_path): + """License file does not exist""" + assert find_license_filename(tmp_path) is None + + +def test_no_valid_license(tmp_path): + """License file exists but with invalid name format so its not accepted""" + license_file = tmp_path / "base_path/invalid_license_format" + create_file(license_file, "First App License") + assert find_license_filename(tmp_path / "base_path") is None + + +@pytest.mark.parametrize( + "license_filename", + [ + f"{name}{extension}" + for name in ["LICENSE", "LICENCE", "COPYING"] + for extension in ["", ".md", ".rst", ".txt"] + ], +) +def test_has_license(tmp_path, license_filename): + """Makes sure all formats are accepted""" + license_file = tmp_path / f"base_path/{license_filename}" + create_file(license_file, "First App License") + assert find_license_filename(tmp_path / "base_path") == license_filename + + +def test_multiple_changefile(tmp_path): + """If there's more than one license, only one is found.""" + + license_file1 = tmp_path / "base_path/LICENCE.txt" + license_file2 = tmp_path / "base_path/LICENSE.md" + create_file(license_file1, "First App License") + create_file(license_file2, "First App Licence") + assert find_license_filename(tmp_path / "base_path") == "LICENSE.md"