Commits

Ronald Oussoren committed 9d02cbf

Update the docstrings for C methods and functions to support inspect.signature on Python 3.4

  • Participants
  • Parent commits 0122380
  • Branches core-cleanup

Comments (0)

Files changed (7)

pyobjc-core/Lib/PyObjCTools/TestSupport.py

     """
     return onlyIf(not is32Bit(), "64-bit only")(function)
 
+def min_python_release(version):
+    """
+    Usage::
+
+        class Tests (unittest.TestCase):
+
+            @min_python_release('3.2')
+            def test_python_3_2(self):
+                pass
+    """
+    parts = tuple(map(int, version.split('.')))
+    return onlyIf(_sys.version_info[:2] >= parts, "Requires Python %s or later"%(version,))
+
 
 def min_os_level(release):
     """
             def testSnowLeopardCode(self):
                 pass
     """
-    return onlyIf(os_release() >= release)
+    return onlyIf(os_release() >= release, "Requires OSX %s or later"%(release,))
 
 def max_os_level(release):
     """
             def testUntilLeopard(self):
                 pass
     """
-    return onlyIf(os_release() <= release)
+    return onlyIf(os_release() <= release, "Requires OSX upto %s"%(release,))
 
 def os_level_between(min_release, max_release):
     """
             def testUntilLeopard(self):
                 pass
     """
-    return onlyIf(min_release <= os_release() <= max_release)
+    return onlyIf(min_release <= os_release() <= max_release, "Requires OSX %s upto %s"%(min_release, max_release))
 
 _poolclass = objc.lookUpClass('NSAutoreleasePool')
 

pyobjc-core/Modules/objc/fsref.m

         .ml_name    = "as_pathname",
         .ml_meth    = (PyCFunction)fsref_as_path,
         .ml_flags   = METH_NOARGS,
-        .ml_doc     = "return POSIX path for this object (Unicode string)"
+        .ml_doc     = "as_pathname()\n\nReturn POSIX path for this object (Unicode string)"
     },
     {
         .ml_name    = "from_pathname",
         .ml_meth    = (PyCFunction)fsref_from_path,
         .ml_flags   = METH_O|METH_CLASS,
-        .ml_doc     = "create FSRef instance for an POSIX path"
+        .ml_doc     = "from_pathname(path)\n\nCreate FSRef instance for an POSIX path"
     },
 
 #if USE_TOOLBOX_OBJECT_GLUE
         .ml_name    = "as_carbon",
         .ml_meth    = (PyCFunction)fsref_as_carbon,
         .ml_flags   = METH_NOARGS,
-        .ml_doc     = "return Carbon.File.FSRef instance for this object"
+        .ml_doc     = "as_carbon()\n\nReturn Carbon.File.FSRef instance for this object"
     },
 #endif /* USE_TOOLBOX_OBJECT_GLUE */
 

pyobjc-core/Modules/objc/fsspec.m

         .ml_name    = "as_carbon",
         .ml_meth    = (PyCFunction)fsspec_as_carbon,
         .ml_flags   = METH_NOARGS,
-        .ml_doc     = "return Carbon.File.FSSpec instance for this object"
+        .ml_doc     = "as_carbon()\n\nReturn Carbon.File.FSSpec instance for this object"
     },
 #endif /* defined(USE_TOOLBOX_OBJECT_GLUE) && !defined(__LP64__) */
     {

pyobjc-core/Modules/objc/module.m

 @end
 
 PyDoc_STRVAR(pyobjc_id_doc,
-  "pyobjc_id(obj) -> int\n"
+  "pyobjc_id(obj)\n"
   "\n"
   "Return the id of the underlying NSObject as an int."
 );
 
 
 PyDoc_STRVAR(repythonify_doc,
-  "repythonify(obj, type='@') -> object\n"
+  "repythonify(obj, type='@')\n"
   "\n"
   "Put an object through the bridge by calling \n"
   "depythonify_c_value then pythonify_c_value.\n"
 #endif /* PY_VERSION_MAJOR == 2 */
 
 PyDoc_STRVAR(lookUpClass_doc,
-  "lookUpClass(class_name) -> class\n"
+  "lookUpClass(class_name)\n"
   "\n"
   "Search for the named classes in the Objective-C runtime and return it.\n"
   "Raises noclass_error when the class doesn't exist.");
 }
 
 PyDoc_STRVAR(set_class_extender_doc,
-    "setClassExtender(func) -> None\n"
+    "_setClassExtender(func)\n"
     "\n"
     "Register a function that will be called to update the class\n"
     "dict of new Objective-C classes and class-proxies. This will\n"
 
 
 PyDoc_STRVAR(getClassList_doc,
-  "getClassList() -> [ cls, ...] n"
+  "getClassList()"
   "\n"
   "Return a list with all Objective-C classes known to the runtime.\n"
 );
 
 
 PyDoc_STRVAR(allocateBuffer_doc,
-         "allocateBuffer(size) -> <r/w buffer>\n"
+         "allocateBuffer(size)\n"
          "\n"
          "Allocate a buffer of memory of size. Buffer is \n"
          "read/write."
 }
 
 PyDoc_STRVAR(currentBundle_doc,
-    "currentBundle() -> bundle\n"
+    "currentBundle()\n"
     "\n"
     "Get the current bundle during module initialization.\n"
     "Works for plug-ins and applications.\n"
 }
 
 PyDoc_STRVAR(objc_splitSignature_doc,
-    "splitSignature(signature) -> list\n"
+    "splitSignature(signature)\n"
     "\n"
     "Split a signature string into a list of items."
 );
 
 
 PyDoc_STRVAR(objc_splitStructSignature_doc,
-    "splitStructSignature(signature) -> structname, fields\n"
+    "splitStructSignature(signature)\n"
     "\n"
     "Split a struct signature string into a list of items."
 );
     "\n"
     "Load the specified functions. List should be a capsule object containing\n"
     "an array of { char*, funcion } structs.");
-
-
+PyDoc_STRVAR(PyObjC_loadSpecialVar_doc,
+    "loadSpecialVar(bundle, module_globals, typeid, name, skip_undefined=True)\n"
+    "\n"
+    "Load a magic cookie object from a bundle. A magic cookie is a \n"
+    "C pointer that represents a CoreFoundation or Objective-C object \n"
+    "that cannot be deferenced.\n");
 
 
 
 
 PyDoc_STRVAR(protocolsForProcess_doc,
-    "protocolsForProcess() -> [Protocols]\n"
+    "protocolsForProcess()\n"
     "\n"
     "Returns a list of Protocol objects that are present in the process"
 );
 }
 
 PyDoc_STRVAR(protocolNamed_doc,
-    "_protocolNamed(name) -> Protocol\n");
+    "_protocolNamed(name)\n");
 static PyObject*
 protocolNamed(PyObject* self __attribute__((__unused__)), PyObject* args, PyObject* kwds)
 {
 
 
 PyDoc_STRVAR(protocolsForClass_doc,
-    "protocolsForClass(cls) -> [Protocols]\n"
+    "protocolsForClass(cls)\n"
     "\n"
     "Returns a list of Protocol objects that the class claims\n"
     "to implement directly."
 }
 
 PyDoc_STRVAR(createOpaquePointerType_doc,
-    "createOpaquePointerType(name, typestr, doc) -> type\n"
+    "createOpaquePointerType(name, typestr, doc)\n"
     "\n"
     "Return a wrapper type for opaque pointers of the given type. The type \n"
     "will be registered with PyObjC and will be used to wrap pointers of the \n"
 }
 
 PyDoc_STRVAR(registerMetaData_doc,
-    "registerMetaDataForSelector(class, selector, metadata) -> None\n"
+    "registerMetaDataForSelector(classObject, selector, metadata)\n"
     "\n"
     "Registers a metadata dictionary for method *selector* in *class*");
 static PyObject*
 
 
 PyDoc_STRVAR(createStructType_doc,
-    "createStructType(name, typestr, fieldnames, doc, pack) -> type\n"
+    "createStructType(name, typestr, fieldnames, doc, pack)\n"
     "\n"
     "Return a wrapper type for structs of the given type. The wrapper will \n"
     "registered with PyObjC and will be used to wrap structs of the given type.\n"
 }
 
 PyDoc_STRVAR(PyObjCIvar_Info_doc,
-    "listInstanceVariables(classOrInstance) -> [ (name, typestr), ... ]\n"
+    "listInstanceVariables(classOrInstance)\n"
     "\n"
     "Return information about all instance variables of an object or class\n"
 );
 PyDoc_STRVAR(PyObjCIvar_Get_doc,
-    "getInstanceVariable(object, name) -> value\n"
+    "getInstanceVariable(object, name)\n"
     "\n"
     "Return the value of an instance variable\n"
 );
 PyDoc_STRVAR(PyObjCIvar_Set_doc,
-    "setInstanceVariable(object, name, value [, updateRefCount])\n"
+    "setInstanceVariable(object, name, value, updateRefCount=False)\n"
     "\n"
     "Modify an instance variable. If the instance variable is an object \n"
     "reference you must include the ``updateRefCount`` argument, otherwise it \n"
 );
 
 PyDoc_STRVAR(registerCFSignature_doc,
-    "registerCFSignature(name, encoding, typeId [, tollfreeName]) -> type\n"
+    "registerCFSignature(name, encoding, typeId, tollfreeName=None) -> type\n"
     "\n"
     "Register a CoreFoundation based type with the bridge. If \n"
     "tollFreeName is supplied the type is tollfree bridged to that class.");
 }
 
 PyDoc_STRVAR(_updatingMetadata_doc,
-    "PRIVATE:");
+    "_updatingMetadata(flag)\n\nPRIVATE FUNCTION");
 static PyObject*
 _updatingMetadata(PyObject* self __attribute__((__unused__)),
         PyObject* args, PyObject* kwds)
 
 
 PyDoc_STRVAR(_makeClosure_doc,
-  "_makeClosure(callable, closureFor, [argIndex]) -> closure, metadata\n"
+  "_makeClosure(callable, closureFor, argIndex=0)\n"
   "\n"
   "Returns a closure object that can be used to call the function from\n"
   "C. This object has no useable interface from Python.\n"
     PyObject* callable;
     PyObject* closureFor;
     PyObjCMethodSignature* methinfo;
-    Py_ssize_t argIndex;
+    Py_ssize_t argIndex = 0;
     Py_ssize_t i;
 
     argIndex=-1;
     /* Associated Object support. Functionality is available on OSX 10.6 or later. */
 
 PyDoc_STRVAR(PyObjC_setAssociatedObject_doc,
-    "setAssociatedObject(object, key, value, [policy=objc.OBJC_ASSOCIATION_RETAIN])\n"
+    "setAssociatedObject(object, key, value, policy=objc.OBJC_ASSOCIATION_RETAIN)\n"
     "\n"
     "Set the value for an object assiociation. Use 'None' as the\n"
     "value to clear an association.");
 
 
 PyDoc_STRVAR(PyObjC_getAssociatedObject_doc,
-    "getAssociatedObject(object, key) -> value\n"
+    "getAssociatedObject(object, key)\n"
     "\n"
     "Get the value for an object assiociation. Returns None \n"
     "when they association doesn't exist.");
         .ml_name    = "propertiesForClass",
         .ml_meth    = (PyCFunction)mod_propertiesForClass,
         .ml_flags   = METH_O,
-        .ml_doc     = "Return information about properties from the runtim",
+        .ml_doc     = "propertiesForClass(classObject)\n\nReturn information about properties from the runtim",
     },
     {
         .ml_name    = "splitSignature",
         .ml_name    = "loadSpecialVar",
         .ml_meth    = (PyCFunction)PyObjC_loadSpecialVar,
         .ml_flags   = METH_VARARGS|METH_KEYWORDS,
+        .ml_doc     = PyObjC_loadSpecialVar_doc
     },
     {
         .ml_name    = "loadBundleFunctions",
         .ml_flags   = METH_VARARGS|METH_KEYWORDS,
         .ml_doc     = _makeClosure_doc
     },
+#if 0
     {
         .ml_name    = "_sockaddrFromPython",
         .ml_meth    = (PyCFunction)PyObjC_SockAddrFromPython,
         .ml_meth    = (PyCFunction)PyObjC_SockAddrToPython,
         .ml_flags   = METH_VARARGS,
     },
+#endif
     {
         .ml_name    = "_ivar_dict",
         .ml_meth    = (PyCFunction)ivar_dict,
         .ml_flags   = METH_NOARGS,
+        .ml_doc     = "_ivar_dict()\n\nPRIVATE FUNCTION\n"
     },
     {
         .ml_name    = "_objc_sync_enter",
         .ml_meth    = (PyCFunction)PyObjC_objc_sync_enter,
         .ml_flags   = METH_VARARGS,
-        "acquire mutex for an object"
+        .ml_doc     = "_objc_sync_enter(object)\n\nacquire mutex for an object"
     },
     {
         .ml_name    = "_objc_sync_exit",
         .ml_meth    = (PyCFunction)PyObjC_objc_sync_exit,
         .ml_flags   = METH_VARARGS,
-        "release mutex for an object"
+        .ml_doc     = "_objc_sync_exit(object)\n\nrelease mutex for an object"
     },
     {
         .ml_name    = "_block_call",
         .ml_name    = "_block_signature",
         .ml_meth    = (PyCFunction)block_signature,
         .ml_flags   = METH_O,
-        "return signature string for a block, or None"
+        "_block_signature(block) -> signature\n\nreturn signature string for a block, or None"
     },
     {
         .ml_name    = "_typestr2typestr",
         .ml_meth    = (PyCFunction)typestr2typestr,
         .ml_flags   = METH_O,
+        .ml_doc     = "_typestr2typestr(value)\nReturns the standard Objective-C version for a PyObjC typestr"
     },
 
 #if    PyObjC_BUILD_RELEASE >= 1006
         .ml_name    = "_loadConstant",
         .ml_meth    = (PyCFunction)PyObjC_LoadConstant,
         .ml_flags   = METH_VARARGS|METH_KEYWORDS,
+        .ml_doc     = "_loadConstant(name, type, magic)\n\nLoad a single C constant and return its value"
     },
     {
         .ml_name    = "_nameForSignature",
         .ml_meth    = (PyCFunction)name_for_signature,
         .ml_flags   = METH_O,
+        .ml_doc     = "_nameForSignature(typestr)\n\nReturn a pretty name for a PyObjC type string"
     },
     {
         .ml_name    = "_rescanClass",
         .ml_meth    = (PyCFunction)force_rescan,
         .ml_flags   = METH_VARARGS|METH_KEYWORDS,
+        .ml_doc     = "_rescanClass(classObject)\n\nForce a rescan of the method table of a class",
     },
     {
         .ml_name    = NULL /* SENTINEL */

pyobjc-core/Modules/objc/objc-object.m

             .tp_alloc       = PyType_GenericAlloc,
             .tp_new         = object_new,
             .tp_del         = (destructor)object_del,
+            .tp_doc         = "objc_object()",
 #ifdef Py_HAVE_LOCAL_LOOKUP
             .tp_dictoffset  = offsetof(PyObjCObject, objc_dict),
 #endif /* Py_HAVE_LOCALLOOKUP */

pyobjc-core/NEWS.txt

 Version 3.0
 -----------
 
+* ``inspect.signature`` works for all functions and methods implemented in C,
+  when using Python 3.4 or later.
+
 * The module ``PyObjCTools.NibClassBuilder`` is not longer available. It only worked
   with ancient versions of Interface Builder (pre-Xcode)
 

pyobjc-core/PyObjCTest/test_inspect_signatures.py

+from PyObjCTools.TestSupport import *
+import objc
+import types
+import inspect
+
+class TestInspectSignatures (TestCase):
+
+    @min_python_release("3.4")
+    def test_module_functions_signature(self):
+        for nm in dir(objc):
+            obj = getattr(objc, nm)
+            if isinstance(obj, types.BuiltinMethodType):
+                self.assertIsNot(inspect.signature(obj), None, "No inspect.signature for %s"%(nm,))
+
+    @min_python_release("3.4")
+    def test_class_signature(self):
+        class_list = [objc.ObjCPointer, objc.objc_meta_class, objc.objc_class,
+            objc.objc_object, objc.pyobjc_unicode, objc.selector, objc.FSRef,
+            objc.FSSpec, objc.ivar, objc.informal_protocol, objc.formal_protocol,
+            objc.varlist, objc.function, objc.IMP, objc.super]
+        if hasattr(objc, 'WeakRef'):
+            class_list.append(objc.WeakRef)
+        for cls in class_list:
+            for nm in dir(cls):
+                if nm in ('__new__', '__subclasshook__', '__abstractmethods__'):
+                    continue
+                obj = getattr(cls, nm)
+                if isinstance(obj, types.BuiltinMethodType):
+                    self.assertIsNot(inspect.signature(obj), None, "No inspect.signature for %s.%s"%(cls.__name__, nm,))
+
+if __name__ == "__main__":
+    main()
+
+
+
+