CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pyobjc-framework-cocoa

Wrappers for the Cocoa frameworks on macOS

Pending
Overview
Eval results
Files

enhanced-classes.mddocs/

Enhanced Classes

Python-friendly enhancements automatically added to native Objective-C classes, providing familiar Python interfaces like dictionary access, iteration support, and context managers. These enhancements make Cocoa objects more natural to use in Python code.

Capabilities

Foundation Class Enhancements

Enhanced methods automatically available on Foundation framework classes to provide Python-like behavior and improved usability.

NSAttributedString Enhancements

def __len__(self):
    """
    Returns the length of the attributed string.
    
    Returns:
        int: Number of characters in the attributed string
        
    Example:
        attr_string = NSAttributedString.alloc().initWithString_("Hello")
        length = len(attr_string)  # Returns 5
    """

NSCache Enhancements (Dictionary-like Interface)

def __getitem__(self, key):
    """
    Gets cached object for key using dictionary-style access.
    
    Args:
        key: Cache key
        
    Returns:
        Cached object or None if NSNull
        
    Raises:
        KeyError: If key not found in cache
        
    Example:
        cache = NSCache.alloc().init()
        value = cache["user_data"]  # Raises KeyError if not found
    """

def get(self, key, default=None):
    """
    Gets cached object for key with optional default value.
    
    Args:
        key: Cache key
        default: Value to return if key not found
        
    Returns:
        Cached object, None if NSNull, or default if not found
        
    Example:
        cache = NSCache.alloc().init()
        value = cache.get("user_data", {})  # Returns {} if not found
    """

def __setitem__(self, key, value):
    """
    Sets cached object for key using dictionary-style assignment.
    
    Args:
        key: Cache key
        value: Object to cache (None values stored as NSNull)
        
    Example:
        cache = NSCache.alloc().init()
        cache["user_data"] = user_object
        cache["setting"] = None  # Stored as NSNull
    """

def __delitem__(self, key):
    """
    Removes cached object for key.
    
    Args:
        key: Cache key to remove
        
    Example:
        cache = NSCache.alloc().init()
        del cache["old_data"]
    """

def clear(self):
    """
    Removes all cached objects.
    
    Example:
        cache = NSCache.alloc().init()
        cache.clear()  # Empty cache
    """

NSHashTable Enhancements (Set-like Interface)

def __len__(self):
    """
    Returns the number of objects in the hash table.
    
    Returns:
        int: Count of objects in hash table
    """

def __iter__(self):
    """
    Iterates over objects in the hash table.
    
    Yields:
        Objects stored in hash table (NSNull converted to None)
    """

def add(self, value):
    """
    Adds object to hash table (None values stored as NSNull).
    
    Args:
        value: Object to add to hash table
    """

def remove(self, value):
    """
    Removes object from hash table.
    
    Args:
        value: Object to remove (None converted to NSNull)
    """

def __contains__(self, value):
    """
    Checks if hash table contains object.
    
    Args:
        value: Object to check for (None converted to NSNull)
        
    Returns:
        bool: True if object is in hash table
    """

def pop(self):
    """
    Removes and returns arbitrary object from hash table.
    
    Returns:
        Arbitrary object from hash table (NSNull converted to None)
    """

def clear(self):
    """
    Removes all objects from hash table.
    """

NSIndexSet Enhancements (Set-like Interface for Indices)

def __len__(self):
    """
    Returns the count of indices in the set.
    
    Returns:
        int: Number of indices in set
    """

def __iter__(self):
    """
    Iterates over indices in ascending order.
    
    Yields:
        int: Indices in the set from lowest to highest
    """

def __reversed__(self):
    """
    Iterates over indices in descending order.
    
    Yields:
        int: Indices in the set from highest to lowest
    """

def __eq__(self, other):
    """
    Compares index sets for equality.
    
    Args:
        other: Another NSIndexSet to compare
        
    Returns:
        bool: True if index sets contain same indices
    """

def __ne__(self, other):
    """
    Compares index sets for inequality.
    
    Args:
        other: Another NSIndexSet to compare
        
    Returns:
        bool: True if index sets contain different indices
    """

def __contains__(self, value):
    """
    Checks if index set contains specific index.
    
    Args:
        value (int): Index to check for
        
    Returns:
        bool: True if index is in set
    """

NSMutableIndexSet Additional Enhancements

def clear(self):
    """
    Removes all indices from the set.
    """

def add(self, value):
    """
    Adds index to the set.
    
    Args:
        value (int): Index to add
    """

def remove(self, value):
    """
    Removes index from the set.
    
    Args:
        value (int): Index to remove
    """

Basic Mapping Enhancements

Classes enhanced with dictionary-like interface for key-value access to their underlying data stores.

# NSMergeConflict (mutable dictionary interface)
def __getitem__(self, key): ...
def __setitem__(self, key, value): ...
def __delitem__(self, key): ...
def __len__(self): ...
def __iter__(self): ...
def keys(self): ...
def values(self): ...
def items(self): ...
def get(self, key, default=None): ...
def clear(self): ...
def update(self, other): ...

# NSUbiquitousKeyValueStore (read-only dictionary interface)
def __getitem__(self, key): ...
def __len__(self): ...
def __iter__(self): ...
def keys(self): ...
def values(self): ...
def items(self): ...
def get(self, key, default=None): ...

# NSUserDefaults (read-only dictionary interface)
def __getitem__(self, key): ...
def __len__(self): ...
def __iter__(self): ...
def keys(self): ...
def values(self): ...
def items(self): ...
def get(self, key, default=None): ...

NSLocale Enhancements (Dictionary-like Access)

def __getitem__(self, key):
    """
    Gets locale information for key using dictionary-style access.
    
    Args:
        key: Locale information key (NSLocale constants)
        
    Returns:
        Locale-specific information for key
        
    Example:
        locale = NSLocale.currentLocale()
        country = locale[NSLocaleCountryCode]
        currency = locale[NSLocaleCurrencyCode]
    """

NSIndexPath Enhancements

def __len__(self):
    """
    Returns the length of the index path.
    
    Returns:
        int: Number of indices in the path
    """

def __getitem__(self, index):
    """
    Gets index at specific position in the path.
    
    Args:
        index (int): Position in the index path
        
    Returns:
        int: Index value at position
    """

def __add__(self, index):
    """
    Creates new index path with additional index appended.
    
    Args:
        index (int): Index to append
        
    Returns:
        NSIndexPath: New index path with appended index
    """

NSURL Enhancements

def __fspath__(self):
    """
    Returns file system path for use with pathlib and os.path.
    
    Returns:
        str: File system path string
        
    Example:
        url = NSURL.fileURLWithPath_("/Users/user/document.txt")
        path = os.path.dirname(url)  # Uses __fspath__ automatically
        pathlib_path = pathlib.Path(url)  # Also works
    """

AppKit Class Enhancements

Enhanced methods automatically available on AppKit framework classes.

NSFontDescriptor Enhancements (Dictionary-like Access)

def __getitem__(self, key):
    """
    Gets font attribute value using dictionary-style access.
    
    Args:
        key: Font attribute key (NSFontAttributeName constants)
        
    Returns:
        Font attribute value
        
    Raises:
        KeyError: If attribute key not found
        
    Example:
        descriptor = NSFontDescriptor.fontDescriptorWithName_size_("Helvetica", 12)
        family = descriptor[NSFontFamilyAttribute]
        size = descriptor[NSFontSizeAttribute]
    """

def get(self, key, default=None):
    """
    Gets font attribute value with optional default.
    
    Args:
        key: Font attribute key
        default: Value to return if key not found
        
    Returns:
        Font attribute value or default
        
    Example:
        descriptor = NSFontDescriptor.fontDescriptorWithName_size_("Helvetica", 12)
        traits = descriptor.get(NSFontTraitsAttribute, {})
        weight = traits.get(NSFontWeightTrait, 0.0) if traits else 0.0
    """

Context Manager Classes

Classes that provide Python context manager support for managing macOS system behaviors during critical operations.

class NSDisabledAutomaticTermination:
    """
    Context manager for temporarily disabling automatic application termination.
    
    Prevents macOS from automatically terminating the application during
    critical operations that must complete without interruption.
    
    Usage:
        with NSDisabledAutomaticTermination():
            # Critical work that shouldn't be interrupted
            save_all_documents()
            perform_cleanup_operations()
    """

class NSDisabledSuddenTermination:
    """
    Context manager for temporarily disabling sudden application termination.
    
    Prevents macOS from suddenly terminating the application (e.g., during
    logout or shutdown) while important operations are in progress.
    
    Usage:
        with NSDisabledSuddenTermination():
            # Critical work that needs to complete
            export_user_data()
            synchronize_with_server()
    """

Safe NSObject Method Enhancements

Enhanced NSObject methods that provide safe selector execution with proper exception handling.

def pyobjc_performSelectorOnMainThread_withObject_waitUntilDone_(self, sel, obj, wait):
    """
    Safely executes selector on main thread with exception handling.
    
    Args:
        sel: Selector to execute
        obj: Object argument to pass to selector
        wait (bool): Whether to wait for completion
        
    Returns:
        Result of selector execution or None if exception occurred
    """

def pyobjc_performSelectorOnMainThread_withObject_modes_(self, sel, obj, modes):
    """
    Safely executes selector on main thread in specific run loop modes.
    
    Args:
        sel: Selector to execute
        obj: Object argument to pass to selector
        modes: List of run loop modes for execution
        
    Returns:
        Result of selector execution or None if exception occurred
    """

def pyobjc_performSelectorOnMainThread_withObject_(self, sel, obj):
    """
    Safely executes selector on main thread and returns result.
    
    Args:
        sel: Selector to execute
        obj: Object argument to pass to selector
        
    Returns:
        Result of selector execution or None if exception occurred
    """

def pyobjc_performSelector_onThread_withObject_waitUntilDone_(self, sel, thread, obj, wait):
    """
    Safely executes selector on specific thread with exception handling.
    
    Args:
        sel: Selector to execute
        thread: NSThread to execute on
        obj: Object argument to pass to selector
        wait (bool): Whether to wait for completion
        
    Returns:
        Result of selector execution or None if exception occurred
    """

def pyobjc_performSelector_onThread_withObject_modes_(self, sel, thread, obj, modes):
    """
    Safely executes selector on thread in specific run loop modes.
    
    Args:
        sel: Selector to execute
        thread: NSThread to execute on
        obj: Object argument to pass to selector
        modes: List of run loop modes for execution
        
    Returns:
        Result of selector execution or None if exception occurred
    """

def pyobjc_performSelector_onThread_withObject_(self, sel, thread, obj):
    """
    Safely executes selector on thread and returns result.
    
    Args:
        sel: Selector to execute
        thread: NSThread to execute on
        obj: Object argument to pass to selector
        
    Returns:
        Result of selector execution or None if exception occurred
    """

def pyobjc_performSelectorInBackground_withObject_(self, sel, obj):
    """
    Safely executes selector in background thread.
    
    Args:
        sel: Selector to execute
        obj: Object argument to pass to selector
        
    Returns:
        None (executes asynchronously)
    """

def pyobjc_performSelector_withObject_afterDelay_(self, sel, obj, delay):
    """
    Safely executes selector after specified delay.
    
    Args:
        sel: Selector to execute
        obj: Object argument to pass to selector
        delay (float): Delay in seconds before execution
        
    Returns:
        None (executes asynchronously)
    """

def pyobjc_performSelector_withObject_afterDelay_inModes_(self, sel, obj, delay, modes):
    """
    Safely executes selector after delay in specific run loop modes.
    
    Args:
        sel: Selector to execute
        obj: Object argument to pass to selector
        delay (float): Delay in seconds before execution
        modes: List of run loop modes for execution
        
    Returns:
        None (executes asynchronously)
    """

Usage Examples

Dictionary-like Collection Access

import Foundation

# NSCache with dictionary interface
cache = Foundation.NSCache.alloc().init()
cache.setName_("MyCache")

# Dictionary-style access
cache["user_session"] = user_session_data
cache["app_preferences"] = preferences_dict

# Get with default
session = cache.get("user_session", create_default_session())

# Check and remove
if "old_cache_key" in cache:
    del cache["old_cache_key"]

# Clear all cached data
cache.clear()

Set-like Collection Operations

import Foundation

# NSMutableIndexSet with set interface
selected_rows = Foundation.NSMutableIndexSet.indexSet()

# Add indices like a set
selected_rows.add(0)
selected_rows.add(5)
selected_rows.add(10)

# Iterate over selected indices
for row_index in selected_rows:
    print(f"Row {row_index} is selected")

# Check membership
if 5 in selected_rows:
    print("Row 5 is selected")

# Set operations
other_selection = Foundation.NSIndexSet.indexSetWithIndex_(3)
selected_rows.addIndexes_(other_selection)

# Clear selection
selected_rows.clear()

Hash Table Operations

import Foundation

# Create hash table with strong memory semantics
hash_table = Foundation.NSHashTable.hashTableWithOptions_(
    Foundation.NSPointerFunctionsStrongMemory
)

# Add items like a set
hash_table.add("item1")
hash_table.add("item2")
hash_table.add(None)  # Automatically converted to NSNull

# Iterate over items
for item in hash_table:
    print(f"Hash table contains: {item}")  # None values converted back

# Check membership and remove
if "item1" in hash_table:
    hash_table.remove("item1")

# Get arbitrary item
if len(hash_table) > 0:
    random_item = hash_table.pop()
    print(f"Removed item: {random_item}")

Enhanced String and Path Operations

import Foundation
import os
import pathlib

# NSAttributedString length
attr_string = Foundation.NSAttributedString.alloc().initWithString_("Hello, World!")
print(f"String length: {len(attr_string)}")  # Uses __len__ enhancement

# NSURL path integration
file_url = Foundation.NSURL.fileURLWithPath_("/Users/user/Documents/file.txt")

# Use with standard Python path operations
directory = os.path.dirname(file_url)  # Uses __fspath__ enhancement  
file_path = pathlib.Path(file_url)     # Also uses __fspath__
parent_dir = file_path.parent
file_exists = file_path.exists()

Font Descriptor Dictionary Access

import AppKit

# Create font descriptor
descriptor = AppKit.NSFontDescriptor.fontDescriptorWithName_size_("Helvetica Neue", 14)

# Dictionary-style access to attributes
family_name = descriptor[AppKit.NSFontFamilyAttribute]
font_size = descriptor[AppKit.NSFontSizeAttribute]

# Safe access with defaults
traits = descriptor.get(AppKit.NSFontTraitsAttribute, {})
if traits:
    weight = traits.get(AppKit.NSFontWeightTrait, 0.0)
    slant = traits.get(AppKit.NSFontSlantTrait, 0.0)
    print(f"Font weight: {weight}, slant: {slant}")

# Create modified descriptor
bold_descriptor = descriptor.fontDescriptorWithSymbolicTraits_(
    AppKit.NSFontBoldTrait
)

Context Managers for System Behavior

import Foundation

# Disable automatic termination during critical operations
with Foundation.NSDisabledAutomaticTermination():
    # Perform critical work that shouldn't be interrupted
    backup_user_data()
    synchronize_settings()
    cleanup_temporary_files()
    # Automatic termination re-enabled automatically

# Disable sudden termination during data operations  
with Foundation.NSDisabledSuddenTermination():
    # Ensure these operations complete even during shutdown
    save_document_changes()
    commit_database_transaction()
    # Sudden termination re-enabled automatically

Safe Selector Execution

import Foundation
import AppKit

# Create string object
string_obj = Foundation.NSString.stringWithString_("hello world")

# Safe execution on main thread
uppercased = string_obj.pyobjc_performSelectorOnMainThread_withObject_waitUntilDone_(
    "uppercaseString",
    None,  # no argument needed
    True   # wait for result
)
print(f"Uppercased: {uppercased}")

# Background execution with error handling
def background_processing():
    result = string_obj.pyobjc_performSelectorInBackground_withObject_(
        "capitalizedString",
        None
    )
    # Result will be None if executed in background

# Delayed execution
string_obj.pyobjc_performSelector_withObject_afterDelay_(
    "uppercaseString",
    None,
    2.0  # Execute after 2 seconds
)

Locale Information Access

import Foundation

# Get current locale
locale = Foundation.NSLocale.currentLocale()

# Dictionary-style access to locale information
country_code = locale[Foundation.NSLocaleCountryCode]
language_code = locale[Foundation.NSLocaleLanguageCode]
currency_code = locale[Foundation.NSLocaleCurrencyCode]
currency_symbol = locale[Foundation.NSLocaleCurrencySymbol]

print(f"Country: {country_code}")
print(f"Language: {language_code}")
print(f"Currency: {currency_code} ({currency_symbol})")

# Create specific locale and access its properties
us_locale = Foundation.NSLocale.localeWithLocaleIdentifier_("en_US")
us_currency = us_locale[Foundation.NSLocaleCurrencyCode]  # "USD"

Index Path Operations

import Foundation

# Create index path for table view
section_0_row_5 = Foundation.NSIndexPath.indexPathForRow_inSection_(5, 0)

# Enhanced operations
path_length = len(section_0_row_5)  # Returns 2 (section and row)
section = section_0_row_5[0]        # Get section index
row = section_0_row_5[1]           # Get row index

# Create new path by adding index
extended_path = section_0_row_5 + 3  # Adds index 3 to path

print(f"Original path length: {path_length}")
print(f"Section: {section}, Row: {row}")
print(f"Extended path: {extended_path}")

Automatic Enhancement Application

All these enhancements are applied automatically when the respective framework modules are imported:

import Foundation  # Automatically applies Foundation enhancements
import AppKit      # Automatically applies AppKit enhancements

# Enhancements are immediately available on all instances
cache = Foundation.NSCache.alloc().init()
cache["key"] = "value"  # Dictionary-style access works immediately

descriptor = AppKit.NSFontDescriptor.fontDescriptorWithName_size_("Arial", 12)
family = descriptor[AppKit.NSFontFamilyAttribute]  # Dictionary access works

The enhancements provide a more Pythonic interface to Cocoa objects while maintaining full compatibility with standard Objective-C methods and patterns.

Install with Tessl CLI

npx tessl i tessl/pypi-pyobjc-framework-cocoa

docs

appkit.md

core-foundation.md

enhanced-classes.md

foundation.md

index.md

pyobjctools.md

tile.json