예제 #1
0
def classAddMethod(cls, name, method):
    """
    Add a single method to a class. 'name' is the ObjC selector
    """
    if isinstance(method, selector):
        sel = selector(method.callable,
                       selector=name,
                       signature=method.signature,
                       isClassMethod=method.isClassMethod)
    else:
        sel = selector(method, selector=name)

    return classAddMethods(cls, [sel])
예제 #2
0
def classAddMethod(cls, name, method):
    """
    Add a single method to a class. 'name' is the ObjC selector
    """
    if isinstance(method, selector):
        sel = selector(method.callable,
                    selector=name,
                    signature=method.signature,
                    isClassMethod=method.isClassMethod)
    else:
        sel = selector(method, selector=name)

    return classAddMethods(cls, [sel])
def makeBundleForClass():
    cb = currentBundle()

    def bundleForClass(cls):
        return cb

    return selector(bundleForClass, isClassMethod=True)
예제 #4
0
def accessor(func, typeSignature='@'):
    """
    Return an Objective-C method object that is conformant with key-value coding
    and key-value observing.
    """

    from inspect import getargspec
    args, varargs, varkw, defaults = getargspec(func)
    funcName = func.__name__
    maxArgs = len(args)
    minArgs = maxArgs - len(defaults or ())
    # implicit self
    selArgs = 1 + funcName.count('_')
    if varargs is not None or varkw is not None:
        raise TypeError('%s can not be an accessor because it accepts varargs or varkw' % (funcName,))

    if not (minArgs <= selArgs <= maxArgs):
        if selArgs == 3 and (minArgs <= 2 <= maxArgs) and funcName.startswith('validate') and funcName.endswith('_error_'):
            return selector(func, signature='Z@:N^@o^@')
        elif minArgs == maxArgs:
            raise TypeError('%s expected to take %d args, but must accept %d from Objective-C (implicit self plus count of underscores)' % (funcName, maxArgs, selArgs))
        else:
            raise TypeError('%s expected to take between %d and %d args, but must accept %d from Objective-C (implicit self plus count of underscores)' % (funcName, minArgs, maxArgs, selArgs))
    
    if selArgs == 3:
        if funcName.startswith('validate') and funcName.endswith('_error_'):
            return selector(func, signature='Z@:N^@o^@')

        if funcName.startswith('insertObject_in') and funcName.endswith('AtIndex_'):
            return selector(func, signature='v@:@i')
        elif funcName.startswith('replaceObjectIn') and funcName.endswith('AtIndex_withObject_'):
            return selector(func, signature='v@:i@')
        
        # pass through to "too many arguments"

    elif selArgs == 2:
        if funcName.startswith('objectIn') and funcName.endswith('AtIndex_'):
            return selector(func, signature='@@:i')
        elif funcName.startswith('removeObjectFrom') and funcName.endswith('AtIndex_'):
            return selector(func, signature='v@:i')
        elif funcName.startswith('get') and funcName.endswith('_range_'):
            return selector(func, signature='@@:{_NSRange=ii}')

        return selector(func, signature="v@:" + typeSignature)

    elif selArgs == 1:
        if typeSignature == '@' and func.func_name.startswith('countOf'):
            typeSignature = 'i'

        return selector(func, signature=typeSignature + "@:")

    raise TypeError("%s takes too many arguments to be an accessor" % (funcName,))
예제 #5
0
 def _typedSelector(func):
     return selector(func, signature=signature)
예제 #6
0
def instancemethod(func):
    return selector(func, isClassMethod=False)
예제 #7
0
def IBAction(func):
    """
    Return an Objective-C method object that can be used as an action
    in Interface Builder.
    """
    return selector(func, signature="v@:@")
예제 #8
0
def initWithObjects_(self, *args):
    if args[-1] is not None:
        raise ValueError, "Need None as the last argument"
    return self.initWithArray_(args[:-1])

CONVENIENCE_METHODS['initWithObjects:'] = (
    ('initWithObjects_', initWithObjects_),
)

def arrayWithObjects_(self, *args):
    if args[-1] is not None:
        raise ValueError, "Need None as the last argument"
    return self.arrayWithArray_(args[:-1])

CONVENIENCE_METHODS['arrayWithObjects:'] = (
    ('arrayWithObjects_', selector(arrayWithObjects_, signature='@@:@', isClassMethod=1)),
)


def setWithObjects_(self, *args):
    if args[-1] is not None:
        raise ValueError, "Need None as the last argument"
    return self.setWithArray_(args[:-1])

CONVENIENCE_METHODS['setWithObjects:'] = (
    ('setWithObjects_', selector(setWithObjects_, signature='@@:@', isClassMethod=1)),
)

def setWithObjects_count_(self, args, count):
    return self.setWithArray_(args[:count])
예제 #9
0
def IBAction(func):
    """
    Return an Objective-C method object that can be used as an action
    in Interface Builder.
    """
    return selector(func, signature="v@:@")
예제 #10
0
 def _namedselector(func):
     return selector(func, selector=name)
예제 #11
0
def _add_convenience_methods(super_class, name, type_dict):
    """
    Add additional methods to the type-dict of subclass 'name' of
    'super_class'.

    CONVENIENCE_METHODS is a global variable containing a mapping from
    an Objective-C selector to a Python method name and implementation.

    CLASS_METHODS is a global variable containing a mapping from
    class name to a list of Python method names and implementation.

    Matching entries from both mappings are added to the 'type_dict'.
    """
    if type_dict.get('__objc_python_subclass__'):
        if 'bundleForClass' not in type_dict:
            cb = currentBundle()
            def bundleForClass(cls):
                return cb
            type_dict['bundleForClass'] = selector(bundleForClass, isClassMethod=True)
        if '__bundle_hack__' in type_dict:
            import warnings
            warnings.warn(
                "__bundle_hack__ is not necessary in PyObjC 1.3+ / py2app 0.1.8+",
                DeprecationWarning)

    for k, sel in type_dict.items():
        if not isinstance(sel, selector):
            continue

        # 
        # Handle some common exceptions to the usual rules:
        #

        sel = sel.selector

        if sel in CONVENIENCE_METHODS:
            v = CONVENIENCE_METHODS[sel]
            for nm, value in v:
                if nm in type_dict and isinstance(type_dict[nm], selector):

                    # Clone attributes of already existing version

                    t = type_dict[nm]
                    v = selector(value, selector=t.selector,
                        signature=t.signature, isClassMethod=t.isClassMethod)

                    type_dict[nm] = v
                else:
                    type_dict[nm] = value

    if name in CLASS_METHODS:
        for nm, value in CLASS_METHODS[name]:
            type_dict[nm] = value


    if name == 'NSObject':
        class kvc (object):
            """
            Key-Value-Coding accessor for Cocoa objects. 
            
            Both attribute access and dict-like indexing will attempt to 
            access the requested item through Key-Value-Coding.
            """
            __slots__ = ('__object',)
            def __init__(self, value):
                self.__object = value

            def __repr__(self):
                return "<KVC accessor for %r>"%(self.__object,)

            def __getattr__(self, key):
                try:
                    return self.__object.valueForKey_(key)
                except KeyError, msg:
                    if hasattr(msg, '_pyobjc_info_') and msg._pyobjc_info_['name'] == 'NSUnknownKeyException':
                        raise AttributeError(key)

                    raise
            def __setattr__(self, key, value):
                if not key.startswith('_'):
                    return self.__object.setValue_forKey_(value, key)
                else:
                    super(kvc, self).__setattr__(key, value)

            def __getitem__(self, key):
                if not isinstance(key, (str, unicode)):
                    raise TypeError("Key must be string")
                return self.__object.valueForKey_(key)

            def __setitem__(self, key, value):
                if not isinstance(key, (str, unicode)):
                    raise TypeError("Key must be string")
                return self.__object.setValue_forKey_(value, key)

        type_dict['_'] = property(kvc)
예제 #12
0
 def makeSignature(func):
     return selector(func, **kw)
예제 #13
0
def _add_convenience_methods(super_class, name, type_dict):
    """
    Add additional methods to the type-dict of subclass 'name' of
    'super_class'.

    CONVENIENCE_METHODS is a global variable containing a mapping from
    an Objective-C selector to a Python method name and implementation.

    CLASS_METHODS is a global variable containing a mapping from
    class name to a list of Python method names and implementation.

    Matching entries from both mappings are added to the 'type_dict'.
    """
    if type_dict.get('__objc_python_subclass__'):
        if 'bundleForClass' not in type_dict:
            cb = currentBundle()

            def bundleForClass(cls):
                return cb

            type_dict['bundleForClass'] = selector(bundleForClass,
                                                   isClassMethod=True)
        if '__bundle_hack__' in type_dict:
            import warnings
            warnings.warn(
                "__bundle_hack__ is not necessary in PyObjC 1.3+ / py2app 0.1.8+",
                DeprecationWarning)

    for k, sel in type_dict.items():
        if not isinstance(sel, selector):
            continue

        #
        # Handle some common exceptions to the usual rules:
        #

        sel = sel.selector

        if sel in CONVENIENCE_METHODS:
            v = CONVENIENCE_METHODS[sel]
            for nm, value in v:
                if nm in type_dict and isinstance(type_dict[nm], selector):

                    # Clone attributes of already existing version

                    t = type_dict[nm]
                    v = selector(value,
                                 selector=t.selector,
                                 signature=t.signature,
                                 isClassMethod=t.isClassMethod)

                    type_dict[nm] = v
                else:
                    type_dict[nm] = value

    if name in CLASS_METHODS:
        for nm, value in CLASS_METHODS[name]:
            type_dict[nm] = value

    if name == 'NSObject':

        class kvc(object):
            """
            Key-Value-Coding accessor for Cocoa objects. 
            
            Both attribute access and dict-like indexing will attempt to 
            access the requested item through Key-Value-Coding.
            """
            __slots__ = ('__object', )

            def __init__(self, value):
                self.__object = value

            def __repr__(self):
                return "<KVC accessor for %r>" % (self.__object, )

            def __getattr__(self, key):
                try:
                    return self.__object.valueForKey_(key)
                except KeyError, msg:
                    if hasattr(
                            msg, '_pyobjc_info_'
                    ) and msg._pyobjc_info_['name'] == 'NSUnknownKeyException':
                        raise AttributeError(key)

                    raise

            def __setattr__(self, key, value):
                if not key.startswith('_'):
                    return self.__object.setValue_forKey_(value, key)
                else:
                    super(kvc, self).__setattr__(key, value)

            def __getitem__(self, key):
                if not isinstance(key, (str, unicode)):
                    raise TypeError("Key must be string")
                return self.__object.valueForKey_(key)

            def __setitem__(self, key, value):
                if not isinstance(key, (str, unicode)):
                    raise TypeError("Key must be string")
                return self.__object.setValue_forKey_(value, key)

        type_dict['_'] = property(kvc)
예제 #14
0
 def makeSignature(func):
     return selector(func, **kw)
예제 #15
0
def _add_convenience_methods(super_class, name, type_dict):
    """
    Add additional methods to the type-dict of subclass 'name' of
    'super_class'.

    CONVENIENCE_METHODS is a global variable containing a mapping from
    an Objective-C selector to a Python method name and implementation.

    CLASS_METHODS is a global variable containing a mapping from
    class name to a list of Python method names and implementation.

    Matching entries from both mappings are added to the 'type_dict'.
    """
    if type_dict.get('__objc_python_subclass__'):
        if 'bundleForClass' not in type_dict:
            cb = currentBundle()
            def bundleForClass(cls):
                return cb
            type_dict['bundleForClass'] = selector(bundleForClass, isClassMethod=True)
            if (HAS_KVO and 
                    '__useKVO__' not in type_dict and
                    isNative(type_dict.get('willChangeValueForKey_')) and
                    isNative(type_dict.get('didChangeValueForKey_'))):
                useKVO = issubclass(super_class, NSObject)
                type_dict['__useKVO__'] = useKVO
        if '__bundle_hack__' in type_dict:
            import warnings
            warnings.warn(
                "__bundle_hack__ is not necessary in PyObjC 1.3+ / py2app 0.1.8+",
                DeprecationWarning)

    for k, sel in type_dict.items():
        if not isinstance(sel, selector):
            continue

        if sel.selector == "alloc" or sel.selector == "allocWithZone:":
            sel.isAlloc = 1

        if sel.selector.endswith(':error:'):
            sigParts = splitSignature(sel.signature)
            if sigParts[-1] == '^@':
                sigParts = sigParts[:-1] + ('o^@',)
                sel.signature = ''.join(sigParts)

        if sel.selector in ( 'copy', 'copyWithZone:',
                      'mutableCopy', 'mutableCopyWithZone:'):
            # These methods transfer ownership to the caller, the runtime uses
            # this information to adjust the reference count.
            sel.doesDonateReference = 1

        sel = sel.selector

        if sel in CONVENIENCE_METHODS:
            v = CONVENIENCE_METHODS[sel]
            for nm, value in v:
                if nm in type_dict and isinstance(type_dict[nm], selector):

                    # Clone attributes of already existing version

                    t = type_dict[nm]
                    v = selector(value, selector=t.selector,
                        signature=t.signature, isClassMethod=t.isClassMethod)
                    v.isAlloc = t.isAlloc

                    type_dict[nm] = v
                else:
                    type_dict[nm] = value

    if name in CLASS_METHODS:
        for nm, value in CLASS_METHODS[name]:
            type_dict[nm] = value
예제 #16
0
 def _typedSelector(func):
     return selector(func, signature=signature)
예제 #17
0
 def _namedselector(func):
     return selector(func, selector=name, signature=signature)
예제 #18
0
 def _namedselector(func):
     return selector(func, selector=name, signature=signature)
예제 #19
0
 def addSignature(function):
     return selector(function, signature=signature)
예제 #20
0
 def _namedselector(func):
     return selector(func, selector=name)
예제 #21
0
def instancemethod(func):
    return selector(func, isClassMethod=False)
예제 #22
0
 def addSignature(function): 
     return selector(function, signature=signature)