{"id":6107,"library":"pyobjc-framework-findersync","title":"PyObjC Framework FinderSync","description":"pyobjc-framework-findersync provides Python wrappers for the macOS FinderSync.framework, allowing Python applications to extend Finder functionality. It is part of the larger PyObjC project, which provides a bridge between Python and Objective-C, enabling Python code to interact with macOS Cocoa frameworks. The PyObjC project, including its framework wrappers, typically releases new versions in alignment with macOS SDK updates and Python version support changes.","status":"active","version":"12.1","language":"en","source_language":"en","source_url":"https://github.com/ronaldoussoren/pyobjc","tags":["macos","objective-c","cocoa","findersync","pyobjc","filesystem","extension"],"install":[{"cmd":"pip install pyobjc-framework-findersync","lang":"bash","label":"Install pyobjc-framework-findersync"}],"dependencies":[{"reason":"Core bridge for Python to Objective-C, required by all pyobjc-framework-* packages.","package":"pyobjc-core"},{"reason":"Provides core UI framework bindings often used with FinderSync extensions, usually pulled in transitively.","package":"pyobjc-framework-AppKit","optional":true},{"reason":"Provides core utility and base classes often used with FinderSync extensions, usually pulled in transitively.","package":"pyobjc-framework-Foundation","optional":true}],"imports":[{"symbol":"FIFinderSyncController","correct":"from FinderSync import FIFinderSyncController"},{"symbol":"FIFinderSync","correct":"from FinderSync import FIFinderSync"}],"quickstart":{"code":"import objc\nfrom FinderSync import FIFinderSync, FIFinderSyncController\nfrom Foundation import NSURL\nimport os\n\nclass MyFinderSyncDelegate(FIFinderSync):\n    \"\"\"\n    A minimal Finder Sync delegate class.\n    In a real Finder Sync Extension, this class would implement methods\n    like `requestBadgeIdentifierForURL_` or `toolbarItemImageForURL_`.\n    \"\"\"\n    def init(self):\n        self = objc.super().init()\n        print(\"MyFinderSyncDelegate initialized.\")\n        return self\n\n    # Example: You would implement FinderSync methods here.\n    # def requestBadgeIdentifierForURL_(self, url):\n    #     print(f\"Requesting badge for: {url}\")\n    #     return \"MyBadgeIdentifier\" # Define this in Info.plist\n\ndef setup_finder_sync():\n    \"\"\"\n    Illustrates how to configure the Finder Sync Controller.\n    Note: This script itself cannot become a Finder Sync Extension.\n    A Finder Sync Extension must be embedded within a host application\n    bundle and configured via its Info.plist to be loaded by Finder.\n    This code demonstrates the PyObjC API usage within such an extension.\n    \"\"\"\n    controller = FIFinderSyncController.sharedExtensionController()\n\n    if controller:\n        # Create an instance of our delegate\n        delegate_instance = MyFinderSyncDelegate.alloc().init()\n        controller.setDelegate_(delegate_instance)\n\n        # Specify directories to monitor\n        # For demonstration, let's try to monitor the user's Downloads folder\n        downloads_path = os.path.expanduser(\"~/Downloads\")\n        downloads_url = NSURL.fileURLWithPath_(downloads_path)\n\n        controller.setDirectoryURLs_([downloads_url])\n\n        print(f\"FinderSyncController delegate set: {controller.delegate()}\")\n        print(f\"Watching directories: {controller.directoryURLs()}\")\n        print(\"\\nNote: For this to take effect, this code must be run from within\")\n        print(\"a properly configured macOS Finder Sync Extension bundle.\")\n        print(\"Simply running this Python script will not register the extension.\")\n    else:\n        print(\"FIFinderSyncController.sharedExtensionController() returned None.\")\n        print(\"This usually means the code is not running within a Finder Sync Extension process.\")\n        print(\"A Finder Sync Extension requires specific macOS bundle setup to function.\")\n\nif __name__ == \"__main__\":\n    setup_finder_sync()","lang":"python","description":"This quickstart demonstrates how to define a Python class as a delegate for the `FIFinderSync` protocol and how to configure the `FIFinderSyncController`. Note that a Finder Sync Extension must be packaged within a macOS application bundle and configured via its `Info.plist` to be loaded by the Finder. This script is for illustrative purposes and will not register a functional Finder Sync extension by itself."},"warnings":[{"fix":"Upgrade to a supported Python version (e.g., Python 3.10+ for PyObjC 12.x).","message":"PyObjC versions frequently drop support for older Python versions. PyObjC 12.0 dropped Python 3.9 support, and PyObjC 11.0 dropped Python 3.8 support. Future versions will likely continue this trend.","severity":"breaking","affected_versions":">=11.0"},{"fix":"Review custom 'init' method implementations, especially those interacting with manual memory management, to ensure compatibility with ARC-compliant reference counting. Most pure Python usage should be unaffected unless directly managing Objective-C object lifetimes.","message":"PyObjC 11.1 aligned its internal behavior for 'init' methods with clang's Automatic Reference Counting (ARC) documentation. This means 'init' methods are now correctly modeled as stealing a reference to self and returning a new reference, potentially affecting custom memory management logic or bridging in older code.","severity":"breaking","affected_versions":">=11.1"},{"fix":"For classes using PyObjC's default __new__, use Objective-C style initialization (alloc().init()). If you need __init__, ensure your class or a superclass provides its own __new__ implementation.","message":"In PyObjC 10.3, calling __init__ on PyObjC-proxied classes was restricted when the class relies on PyObjC's provided __new__. While partially re-enabled in 10.3.1 for user-implemented __new__, code relying on PyObjC's __new__ still cannot use __init__. Instead, use Objective-C style initialization (e.g., MyClass.alloc().init()) or override __new__ and handle initialization there.","severity":"gotcha","affected_versions":">=10.3"},{"fix":"Upgrade to PyObjC 10.1 or later. Alternatively, manually convert `NSURL` to a Python path string using `url.path()` for `file://` URLs.","message":"Prior to PyObjC 10.1, `os.fspath()` did not work correctly with Cocoa `NSURL` objects (or `CFURLRef`) that referred to local filesystem paths, raising a `TypeError` for other URL types. While fixed in 10.1, older PyObjC versions required manual path conversion for `NSURL` objects.","severity":"gotcha","affected_versions":"<10.1"},{"fix":"If encountering issues with free-threading in Python 3.13, consider disabling free-threading or using a different Python version until PyObjC provides full and stable support.","message":"PyObjC 11.0 introduced experimental support for free-threading (PEP 703) in Python 3.13. However, PyObjC does not fully support the experimental free threading in Python 3.13, which required significant changes in its core. Exercise caution and thoroughly test any code running with free-threading enabled.","severity":"gotcha","affected_versions":">=11.0"}],"env_vars":null,"last_verified":"2026-04-14T00:00:00.000Z","next_check":"2026-07-13T00:00:00.000Z"}