{"id":6123,"library":"pyobjc-framework-ituneslibrary","title":"PyObjC iTunesLibrary Framework","description":"This library provides Python bindings for Apple's iTunesLibrary.framework on macOS, allowing Python applications to read and interact with the user's Music or iTunes library database. It's part of the larger PyObjC project, which wraps many macOS frameworks. The library is actively maintained, with frequent releases synchronised with macOS SDK updates and Python version compatibility changes.","status":"active","version":"12.1","language":"en","source_language":"en","source_url":"https://github.com/ronaldoussoren/pyobjc","tags":["macos","pyobjc","framework","itunes","music","objective-c","apple"],"install":[{"cmd":"pip install pyobjc-framework-ituneslibrary","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"This package provides specific framework bindings and relies on the core PyObjC bridge for Objective-C interaction.","package":"pyobjc-core"}],"imports":[{"note":"The primary class for accessing the iTunes/Music library.","symbol":"ITLibrary","correct":"from iTunesLibrary import ITLibrary"}],"quickstart":{"code":"import os\nfrom iTunesLibrary import ITLibrary\n\ndef get_itunes_library_info():\n    \"\"\"\n    Retrieves and prints basic information from the user's Music library.\n    Requires 'Full Disk Access' for the Python application in macOS System Settings.\n    \"\"\"\n    try:\n        # API Version 1 is generally current for basic access\n        library = ITLibrary.libraryWithAPIVersion_error_(1, None)\n        if library:\n            print(f\"Library Name: {library.applicationDisplayName()}\")\n            print(f\"Total Tracks: {len(library.allMediaItems())}\")\n            print(f\"Number of Playlists: {len(library.allPlaylists())}\")\n\n            # Example: Iterate through first 3 tracks\n            print(\"\\nFirst 3 Tracks:\")\n            for i, item in enumerate(library.allMediaItems()):\n                if i >= 3:\n                    break\n                title = item.title()\n                artist = item.artist().name() if item.artist() else \"Unknown Artist\"\n                album = item.album().title() if item.album() else \"Unknown Album\"\n                print(f\"- Title: {title}, Artist: {artist}, Album: {album}\")\n                \n                # Get file path if available\n                if item.location():\n                    file_path = os.fspath(item.location()) # Requires PyObjC 10.1+\n                    # print(f\"  Path: {file_path}\") # Uncomment to see paths\n        else:\n            print(\"Failed to load iTunes Library.\")\n\n    except Exception as e:\n        print(f\"An error occurred: {e}\")\n        print(\"\\nNote: Accessing the iTunes/Music Library typically requires 'Full Disk Access' for your Python application (or its parent process like Terminal/IDE) in macOS System Settings > Privacy & Security.\")\n\nif __name__ == \"__main__\":\n    get_itunes_library_info()","lang":"python","description":"This quickstart demonstrates how to load the user's iTunes/Music library and print some basic information about it. It uses the `ITLibrary` class to access media items and playlists. Note the requirement for macOS 'Full Disk Access' to prevent permission errors."},"warnings":[{"fix":"Ensure your Python environment meets the minimum requirement. PyObjC 12.x requires Python 3.10+, PyObjC 11.x requires Python 3.9+.","message":"PyObjC has periodically dropped support for older Python versions to align with Python's end-of-life schedule and leverage newer Python features.","severity":"breaking","affected_versions":"11.0, 12.0"},{"fix":"Grant 'Full Disk Access' to your terminal, IDE, or the Python executable running the script in System Settings > Privacy & Security > Full Disk Access.","message":"Accessing the iTunes/Music Library.framework requires 'Full Disk Access' permission for the Python application (or its parent process like Terminal/IDE) in macOS System Settings.","severity":"gotcha","affected_versions":"All versions on macOS"},{"fix":"When subclassing Objective-C classes, generally avoid overriding `__init__` if `__new__` is not also overridden. If you must use `__init__`, ensure it's compatible with the new object creation flow or explicitly override `__new__` as well.","message":"PyObjC 10.3 introduced breaking changes regarding the interaction between `__init__` and PyObjC's `__new__` for Objective-C wrapped classes. While partially reverted in 10.3.1 for user-defined `__new__`, direct `__init__` usage with PyObjC-provided `__new__` might still behave differently.","severity":"gotcha","affected_versions":"10.3, 10.3.1+"},{"fix":"Review custom Python wrappers around Objective-C `init` methods, especially those dealing with explicit retain/release cycles (though less common with modern ARC). Ensure your code correctly handles object ownership if directly interacting with such methods.","message":"PyObjC 11.1 changed how it models 'init' family methods (e.g., `initWithObjects_`) to align with Clang's Automatic Reference Counting (ARC) behavior, specifically regarding reference stealing for `self` and returning a new reference. This could affect memory management or object lifecycle in advanced scenarios.","severity":"gotcha","affected_versions":"11.1+"}],"env_vars":null,"last_verified":"2026-04-14T00:00:00.000Z","next_check":"2026-07-13T00:00:00.000Z"}