64 lines
1.8 KiB
Python
Executable File
64 lines
1.8 KiB
Python
Executable File
__all__ = ['classAddMethod', 'Category']
|
|
|
|
from _objc import selector, classAddMethods, objc_class
|
|
|
|
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])
|
|
|
|
|
|
#
|
|
# Syntactic support for categories
|
|
#
|
|
|
|
class _CategoryMeta(type):
|
|
"""
|
|
Meta class for categories.
|
|
"""
|
|
__slots__ = ()
|
|
_IGNORENAMES = ('__module__', '__name__')
|
|
def _newSubclass(cls, name, bases, methods):
|
|
return type.__new__(cls, name, bases, methods)
|
|
_newSubclass = classmethod(_newSubclass)
|
|
|
|
def __new__(cls, name, bases, methods):
|
|
if len(bases) != 1:
|
|
raise TypeError, "Cannot have multiple inheritance with Categories"
|
|
|
|
c = bases[0].real_class
|
|
|
|
if c.__name__ != name:
|
|
raise TypeError, "Category name must be same as class name"
|
|
|
|
m = [ x[1] for x in methods.iteritems() if x[0] not in cls._IGNORENAMES ]
|
|
classAddMethods(c, m)
|
|
return c
|
|
|
|
def Category(cls):
|
|
"""
|
|
Create a category on ``cls``.
|
|
|
|
Usage:
|
|
class SomeClass (Category(SomeClass)):
|
|
def method(self):
|
|
pass
|
|
|
|
``SomeClass`` is an existing class that will be rebound to the same
|
|
value. The side-effect of this class definition is that the methods
|
|
in the class definition will be added to the existing class.
|
|
"""
|
|
if not isinstance(cls, objc_class):
|
|
raise TypeError, "Category can only be used on Objective-C classes"
|
|
retval = _CategoryMeta._newSubclass('Category', (), dict(real_class=cls))
|
|
return retval
|