CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pyobjc

PyObjC is a bridge between Python and Objective-C that allows full featured Cocoa applications to be written in pure Python.

Pending
Overview
Eval results
Files

utilities.mddocs/

Utility Tools

Key-Value Coding, testing support, signal handling, and other utility functions. These tools provide additional functionality for common PyObjC development patterns and specialized use cases.

Capabilities

Key-Value Coding (KVC)

Functions for working with Objective-C's Key-Value Coding system, which provides a generic way to access object properties by name.

def getKey(object, key: str):
    """
    Get a value from an object using Key-Value Coding.
    
    Args:
        object: The object to query
        key (str): The key path to retrieve
        
    Returns:
        The value at the specified key path
        
    Usage:
        from PyObjCTools.KeyValueCoding import getKey
        value = getKey(my_object, "name")
        nested_value = getKey(my_object, "address.street")
    """

def setKey(object, key: str, value):
    """
    Set a value on an object using Key-Value Coding.
    
    Args:
        object: The object to modify
        key (str): The key path to set
        value: The value to set
        
    Usage:
        from PyObjCTools.KeyValueCoding import setKey
        setKey(my_object, "name", "John Doe")
        setKey(my_object, "address.street", "123 Main St")
    """

def getKeyPath(object, keyPath: str):
    """
    Get a value using a key path (synonym for getKey).
    
    Args:
        object: The object to query
        keyPath (str): The key path to retrieve
        
    Returns:
        The value at the specified key path
        
    Usage:
        from PyObjCTools.KeyValueCoding import getKeyPath
        value = getKeyPath(my_object, "user.profile.name")
    """

def setKeyPath(object, keyPath: str, value):
    """
    Set a value using a key path (synonym for setKey).
    
    Args:
        object: The object to modify
        keyPath (str): The key path to set
        value: The value to set
        
    Usage:
        from PyObjCTools.KeyValueCoding import setKeyPath
        setKeyPath(my_object, "user.profile.name", "Jane Smith")
    """

def arrayOfVirtualKeys():
    """
    Get an array of virtual keys for KVC operations.
    
    Returns:
        list: Array of virtual key strings
    """

def dictionaryOfVirtualKeys():
    """
    Get a dictionary of virtual keys for KVC operations.
    
    Returns:
        dict: Dictionary mapping virtual keys to their operations
    """

Testing Support

Classes and functions for PyObjC-specific testing patterns and test case management.

class TestCase:
    """
    Base test case class for PyObjC tests.
    
    Provides PyObjC-specific testing utilities and assertions
    for testing Objective-C bridge functionality.
    """
    
    def assertIsInstance(self, obj, cls):
        """Assert that obj is an instance of cls."""
    
    def assertIsObjCClass(self, cls):
        """Assert that cls is an Objective-C class."""
    
    def assertHasAttr(self, obj, attr):
        """Assert that obj has the specified attribute."""

def main():
    """
    Run the PyObjC test suite.
    
    Discovers and runs all PyObjC tests in the current module
    or package, with appropriate setup and teardown.
    """

def onlyIf(condition: bool, reason: str):
    """
    Decorator to conditionally run a test.
    
    Args:
        condition (bool): Whether the test should run
        reason (str): Reason for skipping if condition is False
        
    Usage:
        @onlyIf(sys.platform == 'darwin', "macOS only")
        def test_cocoa_feature(self):
            pass
    """

def skipUnless(condition: bool, reason: str):
    """
    Decorator to skip a test unless a condition is met.
    
    Args:
        condition (bool): Condition that must be true to run test
        reason (str): Reason for skipping if condition is False
        
    Usage:
        @skipUnless(hasattr(objc, 'VERSION'), "Requires objc.VERSION")
        def test_version_feature(self):
            pass
    """

def fourcc(code: str):
    """
    Convert a four-character code string to an integer.
    
    Args:
        code (str): Four-character code string
        
    Returns:
        int: Integer representation of the four-character code
        
    Usage:
        from PyObjCTools.TestSupport import fourcc
        type_code = fourcc('JPEG')
    """

def cast_int(value):
    """
    Cast a value to an integer for testing purposes.
    
    Args:
        value: The value to cast
        
    Returns:
        int: The integer representation
    """

Signal Handling

Functions for handling Unix signals and Mach signals in PyObjC applications.

def signal(signum: int, handler):
    """
    Install a signal handler for Unix signals.
    
    Args:
        signum (int): Signal number (e.g., signal.SIGTERM)
        handler: Signal handler function
        
    Usage:
        from PyObjCTools.Signals import signal
        import signal as sig
        
        def handle_term(signum, frame):
            print("Received SIGTERM")
            
        signal(sig.SIGTERM, handle_term)
    """

def getsignal(signum: int):
    """
    Get the current signal handler for a signal.
    
    Args:
        signum (int): Signal number
        
    Returns:
        The current signal handler function
        
    Usage:
        from PyObjCTools.Signals import getsignal
        handler = getsignal(signal.SIGTERM)
    """

def dumpStackOnFatalSignal():
    """
    Install signal handlers to dump stack traces on fatal signals.
    
    Automatically installs handlers for common fatal signals (SIGSEGV,
    SIGBUS, SIGFPE, etc.) that will dump a Python stack trace before
    the program terminates.
    
    Usage:
        from PyObjCTools.Signals import dumpStackOnFatalSignal
        dumpStackOnFatalSignal()
    """

def resetFatalSignals():
    """
    Reset signal handlers for fatal signals to their default behavior.
    
    Usage:
        from PyObjCTools.Signals import resetFatalSignals
        resetFatalSignals()
    """

def handleMachSignal(exception_port):
    """
    Handle Mach signals (macOS-specific).
    
    Args:
        exception_port: Mach exception port to monitor
        
    Mach signals are low-level kernel signals used for exception
    handling and debugging on macOS.
    """

Mach Signal Handling (PyObjCTools.MachSignals)

Mach-specific signal handling for advanced debugging on macOS.

def dumpStackOnFatalSignal():
    """
    Mach-specific implementation of stack dumping on fatal signals.
    
    Uses Mach exception handling for more detailed crash information
    than standard Unix signals.
    
    Usage:
        from PyObjCTools.MachSignals import dumpStackOnFatalSignal
        dumpStackOnFatalSignal()
    """

def resetFatalSignals():
    """
    Reset Mach-specific signal handlers to default behavior.
    
    Usage:
        from PyObjCTools.MachSignals import resetFatalSignals
        resetFatalSignals()
    """

Context and Thread Management

Functions for managing execution context and thread locking in PyObjC applications.

def current_bundle():
    """
    Get the current NSBundle object.
    
    Returns:
        NSBundle: The current application bundle, or None if not available
        
    Usage:
        from PyObjCTools import current_bundle
        bundle = current_bundle()
        if bundle:
            resources_path = bundle.resourcePath()
    """

def object_lock(obj):
    """
    Context manager for locking individual Objective-C objects.
    
    Args:
        obj: The Objective-C object to lock
        
    Usage:
        with object_lock(my_object):
            # Thread-safe access to my_object
            my_object.modifyState()
    """

def release_lock():
    """
    Context manager to release the PyObjC global lock.
    
    Temporarily releases the global interpreter lock to allow
    other threads to execute Python or Objective-C code.
    
    Usage:
        with release_lock():
            # Other threads can run while this block executes
            long_running_objc_operation()
    """

Category and Lazy Loading Support

Classes for creating categories and implementing lazy loading patterns.

class Category:
    """
    Helper class for creating Objective-C categories.
    
    Categories allow adding methods to existing Objective-C classes
    without subclassing or modifying the original class definition.
    """
    
    def __init__(self, baseClass):
        """
        Initialize a category for the specified base class.
        
        Args:
            baseClass: The Objective-C class to extend
        """

def inject(targetClass, categoryClass):
    """
    Inject category methods into a target class.
    
    Args:
        targetClass: The class to receive new methods
        categoryClass: The class containing methods to inject
    """

class LazyList:
    """
    Lazy-loaded list implementation for deferred evaluation.
    
    Useful for creating lists of objects that are expensive to create
    and may not all be needed immediately.
    """
    
    def __init__(self, values):
        """
        Initialize with a list of values or value factories.
        
        Args:
            values: List of values or callable factories
        """

class OC_PythonObject:
    """
    Python object wrapper for use in Objective-C contexts.
    
    Allows Python objects to be passed to Objective-C methods
    that expect Objective-C objects, with automatic bridging.
    """

Usage Examples

Key-Value Coding Operations

from PyObjCTools.KeyValueCoding import getKey, setKey
from Foundation import NSMutableDictionary

# Create a mutable dictionary
person = NSMutableDictionary.alloc().init()
person.setObject_forKey_("John Doe", "name")
person.setObject_forKey_(30, "age")

# Create nested structure
address = NSMutableDictionary.alloc().init()
address.setObject_forKey_("123 Main St", "street")
address.setObject_forKey_("Anytown", "city")
person.setObject_forKey_(address, "address")

# Use KVC to access values
name = getKey(person, "name")
print(f"Name: {name}")  # "John Doe"

# Access nested values with key paths
street = getKey(person, "address.street")
print(f"Street: {street}")  # "123 Main St"

# Set values using KVC
setKey(person, "age", 31)
setKey(person, "address.zip", "12345")

print(f"Updated age: {getKey(person, 'age')}")  # 31
print(f"Zip code: {getKey(person, 'address.zip')}")  # "12345"

PyObjC Testing

from PyObjCTools.TestSupport import TestCase, main, onlyIf, skipUnless
import sys
import objc
from Foundation import NSString

class MyPyObjCTests(TestCase):
    
    def test_basic_bridge_functionality(self):
        """Test basic PyObjC bridge operations."""
        # Test string creation
        s = NSString.stringWithString_("Hello")
        self.assertIsInstance(s, NSString)
        self.assertEqual(s.length(), 5)
    
    @onlyIf(sys.platform == 'darwin', "macOS only")
    def test_macos_specific_feature(self):
        """Test macOS-specific functionality."""
        # Test that would only work on macOS
        self.assertTrue(hasattr(objc, 'lookUpClass'))
    
    @skipUnless(hasattr(objc, 'runtime'), "Requires runtime access")
    def test_runtime_features(self):
        """Test runtime introspection features."""
        self.assertIsNotNone(objc.runtime)

if __name__ == '__main__':
    main()

Signal Handling in PyObjC Applications

from PyObjCTools.Signals import signal
import signal as sig
import sys

class MyApplication:
    def __init__(self):
        self.should_quit = False
        self.setup_signal_handlers()
    
    def setup_signal_handlers(self):
        """Set up signal handlers for graceful shutdown."""
        signal(sig.SIGTERM, self.handle_termination)
        signal(sig.SIGINT, self.handle_termination)
    
    def handle_termination(self, signum, frame):
        """Handle termination signals."""
        print(f"Received signal {signum}, shutting down...")
        self.should_quit = True
    
    def run(self):
        """Main application loop."""
        while not self.should_quit:
            # Application logic here
            time.sleep(0.1)
        print("Application shutdown complete")

# Usage
app = MyApplication()
app.run()

Thread-Safe Object Access

from PyObjCTools import object_lock, release_lock
from Foundation import NSMutableArray
import threading

# Shared mutable array
shared_array = NSMutableArray.alloc().init()

def worker_thread(thread_id):
    """Worker thread that modifies shared array."""
    for i in range(10):
        with object_lock(shared_array):
            # Thread-safe modification
            shared_array.addObject_(f"Thread {thread_id}, item {i}")
        
        # Release lock to allow other operations
        with release_lock():
            # Other threads can run while we sleep
            time.sleep(0.01)

# Start multiple threads
threads = []
for i in range(3):
    t = threading.Thread(target=worker_thread, args=(i,))
    threads.append(t)
    t.start()

# Wait for completion
for t in threads:
    t.join()

print(f"Final array count: {shared_array.count()}")

Install with Tessl CLI

npx tessl i tessl/pypi-pyobjc

docs

categories.md

core-bridge.md

decorators.md

framework-loading.md

index.md

protocols.md

type-system.md

utilities.md

tile.json