-
-
Notifications
You must be signed in to change notification settings - Fork 525
File associations #2284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
File associations #2284
Changes from 23 commits
8ece0d5
4264d3b
4b01f9d
4625cbe
1327b07
f82f484
5c8faed
c70ebf6
03f6b55
b61fbe6
904b12b
b493106
6c4b3c2
9323eba
a7f5620
a3c8efd
3799ca9
07c1565
41cdc7a
31f8342
5b28ded
a810a4c
fdbf75d
7412a90
2a3b44d
1533af9
46d2cb6
fd48660
06c12d5
df5909d
8203397
7d96377
7131e6e
bae3210
d51b53b
9374c63
63f594f
21ee20d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Added improved document types (file associations) for Windows and macOS platforms | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -146,6 +146,44 @@ def validate_document_type_config(document_type_id, document_type): | |
| f"The URL associated with document type {document_type_id!r} is invalid: {e}" | ||
| ) | ||
|
|
||
| if sys.platform == "darwin": # pragma: no-cover-if-not-macos | ||
| from briefcase.platforms.macOS.utils import mime_type_to_UTI | ||
|
|
||
| macOS = document_type.setdefault("macOS", {}) | ||
| mime_type = document_type.get("mime_type", None) | ||
| if (uti := mime_type_to_UTI(mime_type)) is not None: | ||
| macOS.setdefault("is_core_type", True) | ||
| macOS.setdefault("LSItemContentTypes", uti) | ||
| macOS.setdefault("LSHandlerRank", "Alternate") | ||
|
freakboy3742 marked this conversation as resolved.
Outdated
|
||
| else: | ||
| # LSItemContentTypes will default to bundle.app_name.document_type_id | ||
| # in the Info.plist template if it is not provided. | ||
| macOS.setdefault("is_core_type", False) | ||
| macOS.setdefault("LSHandlerRank", "Owner") | ||
| macOS.setdefault("UTTypeConformsTo", ["public.data", "public.content"]) | ||
|
|
||
| macOS.setdefault("CFBundleTypeRole", "Viewer") | ||
|
|
||
| content_types = macOS.get("LSItemContentTypes", None) | ||
| if isinstance(content_types, list): | ||
| if len(content_types) > 1: | ||
| raise BriefcaseConfigError( | ||
| f""" | ||
| Document type {document_type_id!r} has multiple content types. Specifying | ||
| multiple values in a LSItemContentTypes key is only valid when multiple document | ||
| types are manually grouped together in the Info.plist file. For Briefcase apps, | ||
| document types are always separately declared in the configuration file, so only | ||
| a single value should be provided. | ||
| """ | ||
| ) | ||
| else: | ||
| macOS["LSItemContentTypes"] = content_types[0] | ||
|
davidfokkema marked this conversation as resolved.
Outdated
|
||
| else: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These no-op branches can be cleaned up if the content type handling is performed before the UTI handling - I'll push an update to do this. |
||
| # This is basically a no-op to satisfy coverage checkers | ||
| content_types = "string or None" | ||
| else: # pragma: no-cover-if-is-macos | ||
| pass | ||
|
|
||
|
|
||
| VALID_BUNDLE_RE = re.compile(r"[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)+$") | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,10 @@ | ||
| import sys | ||
|
|
||
| import pytest | ||
|
|
||
| from briefcase.config import validate_document_type_config | ||
| from briefcase.exceptions import BriefcaseConfigError | ||
| from briefcase.platforms.macOS import utils | ||
|
|
||
|
|
||
| @pytest.fixture | ||
|
|
@@ -160,3 +163,80 @@ def test_validate_document_invalid_extension(invalid_extension, valid_document): | |
| match=r"The extension provided for document type .* is not alphanumeric.", | ||
| ): | ||
| validate_document_type_config("ext", valid_document) | ||
|
|
||
|
|
||
| @pytest.mark.skipif(sys.platform != "darwin", reason="Test runs only on macOS") | ||
| def test_document_type_macOS_config_with_mimetype_single(valid_document): | ||
| """Valid document types don't raise an exception when validated. | ||
|
|
||
| application/pdf is the only valid MIME type for PDF files. | ||
| """ | ||
| valid_document["mime_type"] = "application/pdf" | ||
| validate_document_type_config("ext", valid_document) | ||
| assert "LSItemContentTypes" in valid_document["macOS"].keys() | ||
| assert valid_document["macOS"]["LSItemContentTypes"] == "com.adobe.pdf" | ||
|
davidfokkema marked this conversation as resolved.
Outdated
|
||
|
|
||
|
|
||
| @pytest.mark.skipif(sys.platform != "darwin", reason="Test runs only on macOS") | ||
| def test_document_type_macOS_config_with_mimetype_list(valid_document): | ||
| """Valid document types don't raise an exception when validated. | ||
|
|
||
| text/vcard is _not_ the only valid MIME type for vCard files, others are | ||
| text/directory and text/x-vcard so a list if MIME types is returned | ||
| internally but should still resolve to public.vcard | ||
| """ | ||
| valid_document["mime_type"] = "text/vcard" | ||
| validate_document_type_config("ext", valid_document) | ||
| assert "LSItemContentTypes" in valid_document["macOS"].keys() | ||
| assert valid_document["macOS"]["LSItemContentTypes"] == "public.vcard" | ||
|
|
||
|
|
||
| @pytest.mark.skipif(sys.platform != "darwin", reason="Test runs only on macOS") | ||
| def test_document_type_macOS_config_with_unknown_mimetype(valid_document): | ||
| """Valid document types don't raise an exception when validated. | ||
|
|
||
| Here, a MIME type is provided that is not known to be valid for any file. | ||
| That means that LSItemContentTypes should _not_ be set. | ||
| """ | ||
| valid_document["mime_type"] = "custom/mytype" | ||
| validate_document_type_config("ext", valid_document) | ||
| assert "LSItemContentTypes" not in valid_document["macOS"].keys() | ||
|
|
||
|
|
||
| @pytest.mark.skipif(sys.platform != "darwin", reason="Test runs only on macOS") | ||
| def test_mime_type_to_uti_with_nonexisting_coretypes_file(monkeypatch): | ||
| """Test that mime_type_to_UTI returns None if the coretypes file doesn't exist.""" | ||
| monkeypatch.setattr(utils, "CORETYPES_PATH", "/does/not/exist") | ||
| assert utils.mime_type_to_UTI("application/pdf") is None | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For consistency, this should either (a) be test at the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I follow. Could you elaborate, please?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All the other tests in this file are based on invoking To that end - this test file should also be called
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've reshuffled the tests. Renamed |
||
|
|
||
|
|
||
| @pytest.mark.skipif(sys.platform != "darwin", reason="Test runs only on macOS") | ||
| def test_document_type_macOS_config_with_list_of_content_types(valid_document): | ||
| """Multiple content types are not allowed. | ||
|
|
||
| If a document type has multiple content types, an exception is raised. | ||
| """ | ||
| valid_document.setdefault("macOS", {})["LSItemContentTypes"] = [ | ||
| "com.adobe.pdf", | ||
| "public.vcard", | ||
| ] | ||
| with pytest.raises( | ||
| BriefcaseConfigError, | ||
| match="Document type 'ext' has multiple content types.", | ||
| ): | ||
| validate_document_type_config("ext", valid_document) | ||
|
|
||
|
|
||
| @pytest.mark.skipif(sys.platform != "darwin", reason="Test runs only on macOS") | ||
| def test_document_type_macOS_config_with_list_of_single_content_type(valid_document): | ||
| """Single content type is allowed, even if a list is provided. | ||
|
|
||
| If a document type has a single content type, it is converted to a string. | ||
| """ | ||
| valid_document.setdefault("macOS", {})["LSItemContentTypes"] = "com.adobe.pdf" | ||
| validate_document_type_config("ext", valid_document) | ||
| assert valid_document["macOS"]["LSItemContentTypes"] == "com.adobe.pdf" | ||
|
davidfokkema marked this conversation as resolved.
Outdated
|
||
|
|
||
| valid_document["macOS"]["LSItemContentTypes"] = ["com.adobe.pdf"] | ||
| validate_document_type_config("ext", valid_document) | ||
| assert valid_document["macOS"]["LSItemContentTypes"] == "com.adobe.pdf" | ||
Uh oh!
There was an error while loading. Please reload this page.