PyObjC LinkPresentation Framework
PyObjC is a bridge between Python and Objective-C, enabling Python scripts to interact with macOS Cocoa frameworks. This specific package, `pyobjc-framework-linkpresentation`, provides Python wrappers for Apple's LinkPresentation framework on macOS, allowing developers to fetch and present rich link previews from URLs. It is actively maintained with regular releases, currently at version 12.1.
Warnings
- breaking PyObjC v12.0 dropped support for Python 3.9. Projects targeting older Python versions must use an older PyObjC release (e.g., v11.x for Python 3.9).
- breaking PyObjC v11.0 dropped support for Python 3.8. Projects targeting Python 3.8 must use an older PyObjC release (e.g., v10.x).
- gotcha The behavior of `__init__` and `__new__` for Python subclasses of Objective-C classes changed in v10.3 and was partially reverted in v10.3.1. If you implement `__new__` in a Python subclass, you must ensure `__init__` is callable, which was broken in 10.3. If using PyObjC's provided `__new__`, `__init__` is still not supported.
- breaking PyObjC v11.1 aligned its reference counting for initializer methods (e.g., `init` family) with clang's Automatic Reference Counting (ARC) documentation. Methods in the 'init' family now correctly steal a reference to `self` and return a new reference, which might change behavior if your code relied on previous PyObjC reference counting semantics.
- deprecated The `IMServicePlugIn` framework bindings were removed in PyObjC v10.0, as the framework itself was deprecated in macOS 10.13 and removed in macOS 14.
- gotcha PyObjC v11.0 introduced experimental support for free-threading (PEP 703) with Python 3.13. While this is a significant feature, it's experimental and might not be stable for all use cases, requiring careful testing in multi-threaded environments.
Install
-
pip install pyobjc-framework-linkpresentation
Imports
- LinkPresentation
import LinkPresentation
Quickstart
import LinkPresentation
import Foundation
import objc
import threading
# Use a threading.Event to signal when the metadata fetching is complete
done_fetching = threading.Event()
metadata_result = None
error_result = None
def completion_handler(metadata, error):
global metadata_result, error_result
metadata_result = metadata
error_result = error
done_fetching.set() # Signal that fetching is done
@objc.python_block
def py_completion_handler(metadata, error):
completion_handler(metadata, error)
def fetch_link_metadata(url_string):
global metadata_result, error_result
metadata_result = None
error_result = None
done_fetching.clear()
url = Foundation.NSURL.URLWithString_(url_string)
if not url:
print(f"Invalid URL: {url_string}")
return
provider = LinkPresentation.LPMetadataProvider.alloc().init()
provider.startFetchingMetadataForURL_completionHandler_(url, py_completion_handler)
# Wait for the completion handler to be called
print(f"Fetching metadata for {url_string}...")
if not done_fetching.wait(timeout=10): # Wait up to 10 seconds
print("Fetching timed out.")
return
if error_result:
print(f"Error fetching metadata: {error_result}")
elif metadata_result:
print("Metadata fetched successfully:")
print(f" Title: {metadata_result.title()}")
print(f" URL: {metadata_result.URL()}")
else:
print("No metadata or error received.")
if __name__ == "__main__":
# Fetch metadata for a remote URL
test_url = os.environ.get('TEST_URL', 'https://www.apple.com')
fetch_link_metadata(test_url)
# Create and inspect custom metadata
print("\nCreating custom metadata:")
custom_metadata = LinkPresentation.LPLinkMetadata.alloc().init()
custom_metadata.setOriginalURL_(Foundation.NSURL.URLWithString_("https://example.com/custom"))
custom_metadata.setURL_(Foundation.NSURL.URLWithString_("https://example.com/custom"))
custom_metadata.setTitle_("My Custom Link Title")
print(f" Title: {custom_metadata.title()}")
print(f" URL: {custom_metadata.URL()}")