예제 #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])
예제 #3
0
def makeBundleForClass():
    cb = currentBundle()

    def bundleForClass(cls):
        return cb

    return selector(bundleForClass, isClassMethod=True)
예제 #4
0
파일: _descriptors.py 프로젝트: aosm/pyobjc
def accessor(func, typeSignature=b'@'):
    """
    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=b'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=b'Z@:N^@o^@')

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

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

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

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

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

    raise TypeError("%s takes too many arguments to be an accessor" % (funcName,))
def IBAction(func):
    """
    Return an Objective-C method object that can be used as an action
    in Interface Builder.
    """
    if func is None:
        raise TypeError("IBAction argument must be a callable")
    return selector(func, signature=b"v@:@")
예제 #6
0
def IBAction(func):
    """
    Return an Objective-C method object that can be used as an action
    in Interface Builder.
    """
    if func is None:
        raise TypeError("IBAction argument must be a callable")
    return selector(func, signature=b"v@:@")
 def makeSignature(func):
     return selector(func, **kw)
예제 #8
0
def instancemethod(func):
    return selector(func, isClassMethod=False)
예제 #9
0
파일: _descriptors.py 프로젝트: aosm/pyobjc
 def _namedselector(func):
     return selector(func, selector=name)
 def addSignature(function):
     return selector(function, signature=signature)
예제 #11
0
 def makeSignature(func):
     return selector(func, **kw)
예제 #12
0
def instancemethod(func):
    if func is None:
        raise TypeError("instancemethod argument must be a callable")
    return selector(func, isClassMethod=False)
예제 #13
0
파일: _descriptors.py 프로젝트: aosm/pyobjc
def IBAction(func):
    """
    Return an Objective-C method object that can be used as an action
    in Interface Builder.
    """
    return selector(func, signature=b"v@:@")
예제 #14
0
 def _namedselector(func):
     if func is None:
         raise TypeError("IBAction argument must be a callable")
     return selector(func, selector=name)
예제 #15
0
파일: _descriptors.py 프로젝트: aosm/pyobjc
 def _typedSelector(func):
     return selector(func, signature=signature)
예제 #16
0
파일: _descriptors.py 프로젝트: aosm/pyobjc
def instancemethod(func):
    return selector(func, isClassMethod=False)
def instancemethod(func):
    if func is None:
        raise TypeError("instancemethod argument must be a callable")
    return selector(func, isClassMethod=False)
예제 #18
0
def IBAction(func):
    """
    Return an Objective-C method object that can be used as an action
    in Interface Builder.
    """
    return selector(func, signature=b"v@:@")
예제 #19
0
 def _namedselector(func):
     return selector(func, selector=name)
예제 #20
0
 def _namedselector(func):
     return selector(func, selector=name, signature=signature)
예제 #21
0
 def _typedSelector(func):
     return selector(func, signature=signature)
def accessor(func, typeSignature=b'@'):
    """
    Return an Objective-C method object that is conformant with key-value coding
    and key-value observing.
    """
    if getfullargspec is not None:
        args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations = getfullargspec(func)
    else:
        args, varargs, varkw, defaults = getargspec(func)
        kwonlyargs = kwonlydefaults = annotations = None
    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 or kwonlyargs:
        raise TypeError('%s can not be an accessor because it accepts varargs, varkw or kwonly' % (funcName,))

    if not (minArgs <= selArgs <= maxArgs):
        if 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=_C_NSBOOL + b'@:N^@o^@')

        if funcName.startswith('insertObject_in') and funcName.endswith('AtIndex_'):
            return selector(func, signature=b'v@:' + typeSignature + _C_NSUInteger)
        elif funcName.startswith('replaceObjectIn') and funcName.endswith('AtIndex_withObject_'):
            return selector(func, signature=b'v@:' + _C_NSUInteger + typeSignature)

        elif funcName.startswith('get') and funcName.endswith('_range_'):
            return selector(func, signature=b'v@:o^@' + _C_NSRange)

        elif funcName.startswith('insert') and funcName.endswith('_atIndexes_'):
            return selector(func, signature=b'v@:@@')

        elif funcName.startswith('replace') and 'AtIndexes_with' in funcName:
            return selector(func, signature=b'v@:@@')

        # pass through to "too many arguments"

    elif selArgs == 2:
        if funcName.startswith('objectIn') and funcName.endswith('AtIndex_'):
            return selector(func, signature=typeSignature + b'@:' + _C_NSUInteger)
        elif funcName.startswith('removeObjectFrom') and funcName.endswith('AtIndex_'):
            return selector(func, signature=b'v@:' + _C_NSUInteger)
        elif funcName.startswith('remove') and funcName.endswith('AtIndexes_'):
            return selector(func, signature=b"v@:@")
        elif funcName.endswith('AtIndexes_'):
            return selector(func, signature=b"@@:@")
        elif funcName.startswith('memberOf'):
            return selector(func, signature=_C_NSBOOL + b"@:" + typeSignature)
        elif funcName.startswith('add') and funcName.endswith('Object_'):
            return selector(func, signature=b"v@:" + typeSignature)
        elif funcName.startswith('add'):
            return selector(func, signature=b"v@:@")
        elif funcName.startswith('intersect'):
            return selector(func, signature=b"v@:@")

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

    elif selArgs == 1:
        if funcName.startswith('countOf'):
            typeSignature = _C_NSUInteger
        elif funcName.startswith('enumerator'):
            typeSignature = b"@"


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

    raise TypeError("%s not recognized as an accessor" % (funcName,))
예제 #23
0
def accessor(func, typeSignature=b'@'):
    """
    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=b'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=b'Z@:N^@o^@')

        if funcName.startswith('insertObject_in') and funcName.endswith(
                'AtIndex_'):
            return selector(func, signature=b'v@:@i')
        elif funcName.startswith('replaceObjectIn') and funcName.endswith(
                'AtIndex_withObject_'):
            return selector(func, signature=b'v@:i@')

        # pass through to "too many arguments"

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

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

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

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

    raise TypeError("%s takes too many arguments to be an accessor" %
                    (funcName, ))
예제 #24
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)

    look_at_super = super_class is not None and super_class.__name__ != "Object"

    owner = {}
    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

                elif look_at_super and hasattr(super_class, nm):
                    # Skip, inherit the implementation from a super_class
                    pass

                elif nm not in type_dict or _canOverride(nm, owner, sel):
                    type_dict[nm] = value
                    owner[nm] = sel

    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)
예제 #25
0
def makeBundleForClass():
    cb = currentBundle()
    def bundleForClass(cls):
        return cb
    return selector(bundleForClass, isClassMethod=True)
예제 #26
0
def accessor(func, typeSignature=b"@"):
    """
    Return an Objective-C method object that is conformant with key-value coding
    and key-value observing.
    """
    if getfullargspec is not None:
        (
            args,
            varargs,
            varkw,
            defaults,
            kwonlyargs,
            _kwonlydefaults,
            _annotations,
        ) = getfullargspec(func)
    else:
        args, varargs, varkw, defaults = getargspec(func)
        kwonlyargs = None
    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 or kwonlyargs:
        raise TypeError(
            "%s can not be an accessor because it accepts varargs, varkw or kwonly"
            % (funcName, ))

    if not (minArgs <= selArgs <= maxArgs):
        if 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=_C_NSBOOL + b"@:N^@o^@")

        if funcName.startswith("insertObject_in") and funcName.endswith(
                "AtIndex_"):
            return selector(func,
                            signature=b"v@:" + typeSignature + _C_NSUInteger)
        elif funcName.startswith("replaceObjectIn") and funcName.endswith(
                "AtIndex_withObject_"):
            return selector(func,
                            signature=b"v@:" + _C_NSUInteger + typeSignature)

        elif funcName.startswith("get") and funcName.endswith("_range_"):
            return selector(func, signature=b"v@:o^@" + _C_NSRange)

        elif funcName.startswith("insert") and funcName.endswith(
                "_atIndexes_"):
            return selector(func, signature=b"v@:@@")

        elif funcName.startswith("replace") and "AtIndexes_with" in funcName:
            return selector(func, signature=b"v@:@@")

        # pass through to "too many arguments"

    elif selArgs == 2:
        if funcName.startswith("objectIn") and funcName.endswith("AtIndex_"):
            return selector(func,
                            signature=typeSignature + b"@:" + _C_NSUInteger)
        elif funcName.startswith("removeObjectFrom") and funcName.endswith(
                "AtIndex_"):
            return selector(func, signature=b"v@:" + _C_NSUInteger)
        elif funcName.startswith("remove") and funcName.endswith("AtIndexes_"):
            return selector(func, signature=b"v@:@")
        elif funcName.endswith("AtIndexes_"):
            return selector(func, signature=b"@@:@")
        elif funcName.startswith("memberOf"):
            return selector(func, signature=_C_NSBOOL + b"@:" + typeSignature)
        elif funcName.startswith("add") and funcName.endswith("Object_"):
            return selector(func, signature=b"v@:" + typeSignature)
        elif funcName.startswith("add"):
            return selector(func, signature=b"v@:@")
        elif funcName.startswith("intersect"):
            return selector(func, signature=b"v@:@")

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

    elif selArgs == 1:
        if funcName.startswith("countOf"):
            typeSignature = _C_NSUInteger
        elif funcName.startswith("enumerator"):
            typeSignature = b"@"

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

    raise TypeError("%s not recognized as an accessor" % (funcName, ))
예제 #27
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)

    look_at_super = (super_class is not None and super_class.__name__ != 'Object')

    for k, sel in list(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

                elif look_at_super and hasattr(super_class, nm):
                    # Skip, inherit the implementation from a super_class
                    pass

                elif nm not in type_dict:
                    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 as 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_TYPES):
                    raise TypeError("Key must be string")
                return self.__object.valueForKey_(key)

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

        type_dict['_'] = property(kvc)
예제 #28
0
 def _typedSelector(func):
     if func is None:
         raise TypeError(
             "typedSelector() function argument must be a callable")
     return selector(func, signature=signature)
예제 #29
0
def accessor(func, typeSignature=b"@"):
    """
    Return an Objective-C method object that is conformant with key-value coding
    and key-value observing.
    """
    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 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=_C_NSBOOL + b"@:N^@o^@")

        if funcName.startswith("insertObject_in") and funcName.endswith("AtIndex_"):
            return selector(func, signature=b"v@:" + typeSignature + _C_NSUInteger)
        elif funcName.startswith("replaceObjectIn") and funcName.endswith("AtIndex_withObject_"):
            return selector(func, signature=b"v@:" + _C_NSUInteger + typeSignature)

        elif funcName.startswith("get") and funcName.endswith("_range_"):
            return selector(func, signature=b"v@:o^@" + _C_NSRange)

        elif funcName.startswith("insert") and funcName.endswith("_atIndexes_"):
            return selector(func, signature=b"v@:@@")

        elif funcName.startswith("replace") and "AtIndexes_with" in funcName:
            return selector(func, signature=b"v@:@@")

        # pass through to "too many arguments"

    elif selArgs == 2:
        if funcName.startswith("objectIn") and funcName.endswith("AtIndex_"):
            return selector(func, signature=typeSignature + b"@:" + _C_NSUInteger)
        elif funcName.startswith("removeObjectFrom") and funcName.endswith("AtIndex_"):
            return selector(func, signature=b"v@:" + _C_NSUInteger)
        elif funcName.startswith("remove") and funcName.endswith("AtIndexes_"):
            return selector(func, signature=b"v@:@")
        elif funcName.endswith("AtIndexes_"):
            return selector(func, signature=b"@@:@")
        elif funcName.startswith("memberOf"):
            return selector(func, signature=_C_NSBOOL + b"@:" + typeSignature)
        elif funcName.startswith("add") and funcName.endswith("Object_"):
            return selector(func, signature=b"v@:" + typeSignature)
        elif funcName.startswith("add"):
            return selector(func, signature=b"v@:@")
        elif funcName.startswith("intersect"):
            return selector(func, signature=b"v@:@")

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

    elif selArgs == 1:
        if funcName.startswith("countOf"):
            typeSignature = _C_NSUInteger
        elif funcName.startswith("enumerator"):
            typeSignature = b"@"

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

    raise TypeError("%s not recognized as an accessor" % (funcName,))
예제 #30
0
 def addSignature(function):
     return selector(function, signature=signature)
예제 #31
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)

    look_at_super = (super_class is not None
                     and super_class.__name__ != 'Object')

    for k, sel in list(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

                elif look_at_super and hasattr(super_class, nm):
                    # Skip, inherit the implementation from a super_class
                    pass

                elif nm not in type_dict:
                    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 as 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_TYPES):
                    raise TypeError("Key must be string")
                return self.__object.valueForKey_(key)

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

        type_dict['_'] = property(kvc)
 def _typedSelector(func):
     if func is None:
         raise TypeError("typedSelector() function argument must be a callable")
     return selector(func, signature=signature)
 def _namedselector(func):
     if func is None:
         raise TypeError("IBAction argument must be a callable")
     return selector(func, selector=name)
예제 #34
0
def accessor(func, typeSignature=b'@'):
    """
    Return an Objective-C method object that is conformant with key-value coding
    and key-value observing.
    """
    if getfullargspec is not None:
        args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations = getfullargspec(
            func)
    else:
        args, varargs, varkw, defaults = getargspec(func)
        kwonlyargs = kwonlydefaults = annotations = None
    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 or kwonlyargs:
        raise TypeError(
            '%s can not be an accessor because it accepts varargs, varkw or kwonly'
            % (funcName, ))

    if not (minArgs <= selArgs <= maxArgs):
        if 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=_C_NSBOOL + b'@:N^@o^@')

        if funcName.startswith('insertObject_in') and funcName.endswith(
                'AtIndex_'):
            return selector(func,
                            signature=b'v@:' + typeSignature + _C_NSUInteger)
        elif funcName.startswith('replaceObjectIn') and funcName.endswith(
                'AtIndex_withObject_'):
            return selector(func,
                            signature=b'v@:' + _C_NSUInteger + typeSignature)

        elif funcName.startswith('get') and funcName.endswith('_range_'):
            return selector(func, signature=b'v@:o^@' + _C_NSRange)

        elif funcName.startswith('insert') and funcName.endswith(
                '_atIndexes_'):
            return selector(func, signature=b'v@:@@')

        elif funcName.startswith('replace') and 'AtIndexes_with' in funcName:
            return selector(func, signature=b'v@:@@')

        # pass through to "too many arguments"

    elif selArgs == 2:
        if funcName.startswith('objectIn') and funcName.endswith('AtIndex_'):
            return selector(func,
                            signature=typeSignature + b'@:' + _C_NSUInteger)
        elif funcName.startswith('removeObjectFrom') and funcName.endswith(
                'AtIndex_'):
            return selector(func, signature=b'v@:' + _C_NSUInteger)
        elif funcName.startswith('remove') and funcName.endswith('AtIndexes_'):
            return selector(func, signature=b"v@:@")
        elif funcName.endswith('AtIndexes_'):
            return selector(func, signature=b"@@:@")
        elif funcName.startswith('memberOf'):
            return selector(func, signature=_C_NSBOOL + b"@:" + typeSignature)
        elif funcName.startswith('add') and funcName.endswith('Object_'):
            return selector(func, signature=b"v@:" + typeSignature)
        elif funcName.startswith('add'):
            return selector(func, signature=b"v@:@")
        elif funcName.startswith('intersect'):
            return selector(func, signature=b"v@:@")

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

    elif selArgs == 1:
        if funcName.startswith('countOf'):
            typeSignature = _C_NSUInteger
        elif funcName.startswith('enumerator'):
            typeSignature = b"@"

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

    raise TypeError("%s not recognized as an accessor" % (funcName, ))
예제 #35
0
파일: _descriptors.py 프로젝트: aosm/pyobjc
 def _namedselector(func):
     return selector(func, selector=name, signature=signature)