Commits

Ronald Oussoren committed 86eb251

Leading underscores are not translated anymore into colons when ObjC-ifying a
python method name.

  • Participants
  • Parent commits c334749
  • Branches pyobjc-ancient

Comments (0)

Files changed (5)

File Doc/intro.txt

 1. Replace all colons in the selector with underscores:
   
     - ``someMethod:withFoo:andBar:`` translates to ``someMethod_withFoo_andBar_``
-  
+
 2. If the result ``class`` or ``raise`` (Python keywords), append two underscores:
   
     - ``class`` translates to ``class__``

File Lib/objc/test/test_subclass.py

         self.assert_('dealloc' in aList)
         self.assert_('__del__' in aList)
 
+    def testMethodNames(self):
+
+        class MethodNamesClass (NSObject):
+            def someName_andArg_(self, name, arg):
+                pass
+
+            def _someName_andArg_(self, name, arg):
+                pass
+
+
+            def raise__(self):
+                pass
+
+            def froobnicate__(self):
+                pass
+
+        # XXX: workaround for a 'feature' in class-builder.m, that code 
+        # ignores methods whose name starts with two underscores. That code
+        # is not necessary, or the other ways of adding methods to a class
+        # should be changed.
+        def __foo_bar__(self, a, b, c):
+            pass
+
+        MethodNamesClass.__foo_bar__ = __foo_bar__
+
+        self.assertEquals(MethodNamesClass.someName_andArg_.selector,
+                'someName:andArg:')
+        self.assertEquals(MethodNamesClass._someName_andArg_.selector,
+                '_someName:andArg:')
+        self.assertEquals(MethodNamesClass.__foo_bar__.selector,
+                '__foo_bar__')
+        self.assertEquals(MethodNamesClass.raise__.selector,
+                'raise')
+        self.assertEquals(MethodNamesClass.froobnicate__.selector,
+                'froobnicate::')
+
 
 if __name__ == '__main__':
     unittest.main()

File Modules/objc/class-builder.m

 			if (pyname == NULL) continue;
 
 			ocname = PyString_AS_STRING(pyname);
+			
+			/* XXX: Why is this needed? */
 			if (ocname[0] == '_' && ocname[1] == '_') {
 				/* Skip special methods */
 				continue;

File Modules/objc/selector.m

 		}
 	}
 
-	cur = strchr(buf, '_');
+	/* Skip leading underscores, '_doFoo_' is probably '_doFoo:' in 
+	 * Objective-C, not ':doFoo:'.
+	 *
+	 * Also if the name starts and ends with two underscores, return
+	 * it unmodified. This avoids mangling of Python's special methods.
+	 *
+	 * Both are heuristics and could be the wrong choice, but either 
+	 * form is very unlikely to exist in ObjC code.
+	 */
+	cur = buf;
+
+	if (ln > 5) {
+		if (cur[0] == '_' && cur[1] == '_' &&
+		    cur[ln-1] == '_' && cur[ln-2] == '_') {
+			return sel_registerName(buf);
+		}
+	}
+
+	while (*cur == '_') {
+		cur++;
+	}
+
+	/* Replace all other underscores by colons */
+	cur = strchr(cur, '_');
 	while (cur != NULL) {
 		*cur = ':';
 		cur = strchr(cur, '_');
   values in destructors. This seems to solve at least one memory managment
   issue.
 
+- A slight complication in the naming rule:
+
+  1) Don't translate leading underscores in Python to colons in Objective-C,
+     ``_doFoo_andBar_`` in Python will be ``_doFoo:andBar:`` in Objective-C.
+
+  2) If a name starts and ends with double underscores don't modify the
+     name at all when moving from Python to Objective-C, 
+     ``__foobar__`` in Python will stay that way in Objective-C.
+
+  These changes fix some minor annoyances with the older scheme. Note that
+  the translation from Objective-C to Python is unmodified and is entirely
+  consistent with the modified rules for translating from Python to Objective-C.
+
 
 Version 1.3.7 (2005-07-06)
 --------------------------