Esempio n. 1
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)
Esempio n. 2
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)
Esempio n. 3
0
def makeBundleForClass():
    cb = currentBundle()
    def bundleForClass(cls):
        return cb
    return selector(bundleForClass, isClassMethod=True)