diff --git a/pep-0575.rst b/pep-0575.rst index da9d99c91..4576a29a4 100644 --- a/pep-0575.rst +++ b/pep-0575.rst @@ -95,6 +95,8 @@ with some differences: replacing ``method_descriptor``. Also ``__qualname__`` will use ``__objclass__`` as namespace (instead of ``m_self`` before). + For methods of extension types, it is automatically assigned as the defining class + (``__class__`` in plain Python). #. Argument Clinic [#clinic]_ is not supported. @@ -139,7 +141,7 @@ These are the relevant C structures:: PyObject_HEAD PyCFunctionDef *m_ml; /* Description of the C function to call */ PyObject *m_self; /* __self__: anything, can be NULL; readonly */ - PyObject *m_module; /* __module__: anything */ + PyObject *m_module; /* __module__: anything (typically str) */ PyTypeObject *m_objclass; /* __objclass__: type or NULL; readonly */ PyObject *m_weakreflist; /* List of weak references */ } PyBaseFunctionObject; @@ -224,6 +226,11 @@ And ``__defaults__`` is not required to be used for calling the function. Apart from adding these extra attributes, ``defined_function`` behaves exactly the same as ``base_function``. +**TODO**: maybe find a better name for ``defined_function``. +Other proposals: ``builtout_function`` (a function that is better built out; pun on builtin), +``generic_function`` (original proposal but conflicts with ``functools.singledispatch`` generic functions), +``user_function`` (defined by the user as opposed to CPython). + function -------- @@ -808,6 +815,64 @@ are deprecated and no longer used by CPython itself. For now, they are kept for backwards compatibility. +Two-phase Implementation +======================== + +**TODO**: this section is optional. When accepting this PEP, it should +be decided whether to apply this two-phase implementation or not. + +As mentioned above, the `changes to types and inspect`_ can break some +existing code. +In order to further minimize breakage, this PEP could be implemented +in two phases. + +Phase one: duplicate classes +---------------------------- + +Implement this PEP but duplicate the classes ``bound_method`` +and ``builtin_function``. +Add a new class ``builtin_method`` which is an exact copy of ``builtin_function`` +add a new class ``bound_builtin_method`` which is an exact copy +of ``bound_method`` (in both cases, only the name would differ). + +The class ``builtin_method`` will be used for unbound methods +of extension types. +It should be seen as continuation of the existing class +``method-descriptor``. +This ensures 100% backwards compatibility for these objects +(except for added attributes and maybe the ``repr()``). + +The same would be done for bound methods of extension types: +these will be instances of ``bound_builtin_method``. +This ensures full backwards compatibility, except for code +assuming that ``types.BuiltinFunctionType`` is the same as ``types.BuiltinMethodType``. + +For ``inspect``, we keep but deprecate the functions +``isbuiltin``, ``ismethod`` and ``ismethoddescriptor``. +To replace these, new functions ``isbuiltinfunction``, ``isboundmethod`` +and ``isgetdescriptor`` (other possible names: ``isreaddescriptor`` or ``isdescriptor``) +are added. +The function ``isbuiltinfunction`` checks for instances of ``builtin_function`` +and ``builtin_method``. +``isboundmethod`` checks for both ``bound_method`` and ``bound_builtin_method``. +And ``isgetdescriptor`` checks for non-data descriptors +which are not instances of ``base_function``. + +Since showing an actual ``DeprecationWarning`` would affect a lot +of correctly-functioning code, +the deprecations would only appear in the documentation. +Another reason is that it is hard to show warnings for calling ``isinstance(x, t)`` +(but it could be done using ``__instancecheck__`` hacking) +and impossible for ``type(x) is t``. + +Phase two +--------- + +Phase two is what is actually described in the rest of this PEP: +the duplicate classes would be merged and the ``inspect`` functions +adjusted accordingly. + + Reference Implementation ========================