Ronald Oussoren avatar Ronald Oussoren committed 3587439

More tests and documentation tweak

Comments (0)

Files changed (2)

pyobjc-core/Doc/lib/module-objc.rst

 
 .. function:: classAddMethod(cls, name, method)
 
-   Adds function *method* as selector *name* to the given class.
+   Adds function *method* as selector *name* to the given class. When *method*
+   is a selector the signature and class-method-ness are copied from the selector.
+
+   .. note::
+
+      Adding a selector that's defined in Objective-C to another class will raise
+      an exception.
 
 .. class:: Category
 

pyobjc-core/PyObjCTest/test_methodedits.py

         return "<pure-py>"
 
 class TestFromObjCSuperToObjCClass(TestCase):
+    def testClassAddMethod(self):
+        import objc._category as mod
+
+        orig_classAddMethods = mod.classAddMethods
+        try:
+            l = []
+            def classAddMethods(cls, values):
+                self.assertIsInstance(cls, objc.objc_class)
+                for item in values:
+                    self.assertIsInstance(item, objc.selector)
+                l.append((cls, values))
+
+            mod.classAddMethods = classAddMethods
+
+            def my_python_description(self):
+                return "foo the bar"
+
+            objc.classAddMethod(NSObject, b"python_description", my_python_description)
+            self.assertEqual(len(l), 1)
+            self.assertIs(l[0][0], NSObject)
+            self.assertEqual(len(l[0][1]), 1)
+            m = l[0][1][0]
+            self.assertIsInstance(m, objc.selector)
+            self.assertIs(m.callable, my_python_description)
+            self.assertEqual(m.selector, b"python_description")
+            self.assertEqual(m.signature, b"@@:")
+
+            @objc.typedSelector(b"q@:")
+            def myAction(self):
+                return 1
+
+            l[:] = []
+            objc.classAddMethod(NSObject, b"value",  myAction)
+            self.assertIs(l[0][0], NSObject)
+            self.assertEqual(len(l[0][1]), 1)
+            m = l[0][1][0]
+            self.assertIsInstance(m, objc.selector)
+            self.assertIs(m.callable, myAction.callable)
+            self.assertEqual(m.selector, b"value")
+            self.assertEqual(m.signature, b"q@:")
+
+            
+            # Cannot add native selectors:
+            self.assertRaises(AttributeError, objc.classAddMethod, NSObject, b"descriptionAlias", NSObject.description)
+
+        finally:
+            mod.classAddMethods = orig_classAddMethods
+
+
     def testBasicBehavior(self):
         anInstance = Methods.new()
         self.assertEqual(anInstance.description(), "<methods>")
         self.assertTrue(not o.categoryMethod2())
         self.assertEqual(Methods.anotherClassMethod(), "hello")
 
+    def testNoInstanceVariables(self):
+        global Methods
+
+        try:
+            class Methods(objc.Category(Methods)):
+                outlet = objc.IBOutlet()
+
+        except TypeError:
+            pass
+
+        else:
+            self.fail("Can add instance variable in a category")
+
     def testObjCClassCategory(self):
         NSObject = objc.lookUpClass('NSObject')
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.