diff --git a/pep-0575.rst b/pep-0575.rst index 9f3a6b513..b3b71e411 100644 --- a/pep-0575.rst +++ b/pep-0575.rst @@ -18,7 +18,7 @@ built-in functions (implemented in C) and Python functions. Mainly, make built-in functions behave more like Python functions without sacrificing performance. -A new base class ``basefunction`` is introduced and the various function +A new base class ``base_function`` is introduced and the various function classes, as well as ``method`` (renamed to ``bound_method``), inherit from it. We also allow subclassing of some of these function classes. @@ -60,13 +60,13 @@ This is the new class hierarchy for functions and methods:: object | | - basefunction - / | \ - / | \ - / | generic_function - / | \ - builtin_function (*) | \ - | python_function + base_function + / | \ + / | \ + / | defined_function + / | \ + builtin_function (*) | \ + | python_function | bound_method (*) @@ -76,10 +76,10 @@ the others do. There is no difference between functions and unbound methods, while bound methods are instances of ``bound_method``. -basefunction ------------- +base_function +------------- -The class ``basefunction`` becomes a new base class for all function types. +The class ``base_function`` becomes a new base class for all function types. It behaves like the existing ``builtin_function_or_method`` with some differences: @@ -94,24 +94,16 @@ with some differences: This is mainly meant to support unbound methods of extension types, replacing ``method_descriptor``. Also ``__qualname__`` will use ``__objclass__`` as namespace - (instead of ``__self__``). + (instead of ``m_self`` before). #. Argument Clinic [#clinic]_ is not supported. #. The field ``ml_doc`` and the attributes ``__doc__`` and ``__text_signature__`` are gone. -#. A new flag ``METH_CUSTOM`` for ``ml_flags`` which prevents automatic - generation of a ``builtin_function``, see `Automatic creation of built-in functions`_. - #. A new flag ``METH_ARG0_FUNCTION`` for ``ml_flags``. If this flag is set, the C function stored in ``ml_meth`` will be called with first argument - equal to the function object instead of ``__self__``. - -#. A new flag ``METH_ARG0_NO_SLICE`` for ``ml_flags``. - If this flag is *not* set and ``__self__`` is not set, - then the first positional argument is treated as ``__self__``. - For more details, see `Self slicing`_. + equal to the function object instead of ``m_self``. #. A new flag ``METH_BINDING`` for ``ml_flags`` which only applies to functions of a module (not methods of a class). @@ -119,6 +111,7 @@ with some differences: of the module. This allows the function to behave more like a Python function as it enables ``__get__``. + This flag also enables `Self slicing`_. #. A new flag ``METH_PYTHON`` for ``ml_flags``. This flag indicates that this function should be treated as Python function. @@ -126,12 +119,15 @@ with some differences: against the duck typing philosophy. It is still needed in a few places though, for example `Profiling`_. -The goal of ``basefunction`` is that it supports all different ways +#. A new flag ``METH_CUSTOM`` for ``ml_flags`` which prevents automatic + generation of a ``builtin_function``, see `Automatic creation of built-in functions`_. + +The goal of ``base_function`` is that it supports all different ways of calling functions and methods in just one structure. For example, the new flag ``METH_ARG0_FUNCTION`` will be used by the implementation of Python functions. -It is not possible to directly create instances of ``basefunction`` +It is not possible to directly create instances of ``base_function`` (``tp_new`` is ``NULL``). However, it is legal for C code to manually create instances. @@ -157,10 +153,17 @@ These are the relevant C structures:: Subclasses may extend ``PyCFunctionDef`` with extra fields. +The Python attribute ``__self__`` returns ``m_self``, +except if ``METH_STATIC`` is set. +In that case, ``None`` is returned. +If ``m_self`` is ``NULL``, then there is no ``__self__`` attribute at all. +For that reason, we write either ``m_self`` or ``__self__`` in this PEP +with slightly different meanings. + builtin_function ---------------- -This is a copy of ``basefunction``, with the following differences: +This is a copy of ``base_function``, with the following differences: #. ``m_ml`` points to a ``PyMethodDef`` structure, extending ``PyCFunctionDef`` with an additional ``ml_doc`` @@ -174,38 +177,39 @@ This is a copy of ``basefunction``, with the following differences: const char *ml_doc; } PyMethodDef; - Note that ``PyMethodDef`` is part of the Python Stable ABI [#ABI]_, - so we cannot change this structure. + Note that ``PyMethodDef`` is part of the Python Stable ABI [#ABI]_ + and it is used by most extension modules, + so we absolutely cannot change this structure. #. Argument Clinic [#clinic]_ is supported. The type object is ``PyTypeObject PyCFunction_Type`` and we define ``PyCFunctionObject`` as alias of ``PyBaseFunctionObject``. -generic_function +defined_function ---------------- -The class ``generic_function`` (a subclass of ``basefunction``) adds +The class ``defined_function`` (a subclass of ``base_function``) adds support for various standard attributes which are used in ``inspect``. This would be a good class to use for auto-generated C code, for example produced by Cython [#cython]_. The layout of the C structure is as follows:: - PyTypeObject PyGenericFunction_Type; + PyTypeObject PyDefinedFunction_Type; typedef struct { PyBaseFunctionObject base; PyObject *func_name; /* __name__: string */ PyObject *func_qualname; /* __qualname__: string */ PyObject *func_doc; /* __doc__: can be anything or NULL */ - PyObject *func_code; /* __code__: code or NULL */ + PyObject *func_code; /* __code__: code */ + PyObject *func_globals; /* __globals__: anything; readonly */ PyObject *func_defaults; /* __defaults__: tuple or NULL */ PyObject *func_kwdefaults; /* __kwdefaults__: dict or NULL */ - PyObject *func_annotations; /* __annotations__: dict or NULL */ - PyObject *func_globals; /* __globals__: anything or NULL; readonly */ PyObject *func_closure; /* __closure__: tuple of cell objects or NULL; readonly */ + PyObject *func_annotations; /* __annotations__: dict or NULL */ PyObject *func_dict; /* __dict__: dict or NULL */ - } PyGenericFunctionObject; + } PyDefinedFunctionObject; This class adds various slots like ``__doc__`` and ``__code__`` to access the C attributes. The slot ``__name__`` returns ``func_name``. @@ -218,7 +222,7 @@ possibly only a few fields may be filled in. And ``__defaults__`` is not required to be used for calling the function. Apart from adding these extra attributes, -``generic_function`` behaves exactly the same as ``basefunction``. +``defined_function`` behaves exactly the same as ``base_function``. python_function --------------- @@ -227,8 +231,9 @@ This is the class meant for functions implemented in Python, formerly known as ``function``. Unlike the other function types, instances of ``python_function`` can be created from Python code. +This is not changed, so we do not describe the details in this PEP. -The layout of the C structure is almost the same as ``generic_function``:: +The layout of the C structure is almost the same as ``defined_function``:: PyTypeObject PyFunction_Type; @@ -237,11 +242,11 @@ The layout of the C structure is almost the same as ``generic_function``:: PyObject *func_name; /* __name__: string */ PyObject *func_qualname; /* __qualname__: string */ PyObject *func_doc; /* __doc__: can be anything or NULL */ - PyObject *func_code; /* __code__: code or NULL */ + PyObject *func_code; /* __code__: code */ PyObject *func_defaults; /* __defaults__: tuple or NULL */ PyObject *func_kwdefaults; /* __kwdefaults__: dict or NULL */ PyObject *func_annotations; /* __annotations__: dict or NULL */ - PyObject *func_globals; /* __globals__: anything or NULL; readonly */ + PyObject *func_globals; /* __globals__: anything; readonly */ PyObject *func_closure; /* __closure__: tuple of cell objects or NULL; readonly */ PyObject *func_dict; /* __dict__: dict or NULL */ PyCFunctionDef _ml; /* Storage for base.m_ml */ @@ -249,17 +254,21 @@ The layout of the C structure is almost the same as ``generic_function``:: The only difference is an ``_ml`` field which reserves space to be used by ``base.m_ml``. -However, it is not required that ``base.m_ml`` points to ``_ml``. -The constructor takes care of setting up ``base.m_ml``. -In particular, it sets the ``METH_PYTHON`` flag. +When constructing an instance of ``python_function`` from ``code`` and ``globals``, +an instance is created with ``base.m_ml = &_ml``, +``base.m_self = NULL`` and with the ``METH_PYTHON`` flag set. + +To make subclassing easier, we also add a copying constructor: +if ``f`` is an instance of ``defined_function`` with the ``METH_PYTHON`` +flag set, then ``types.FunctionType(f)`` copies ``f``. bound_method ------------ The class ``bound_method`` is used for all bound methods, regardless of the class of the underlying function. -It adds one new attribute on top of ``basefunction``: +It adds one new attribute on top of ``base_function``: ``__func__`` points to that function. ``bound_method`` replaces the old ``method`` class @@ -267,25 +276,28 @@ which was used only for Python functions bound as method. There is a complication because we want to allow constructing a method from an arbitrary callable. -This may be an already-bound method or simply not an instance of ``basefunction``. +This may be an already-bound method or simply not an instance of ``base_function``. Therefore, in practice there are two kinds of methods: -for arbitrary callables, we use a single fixed ``PyCFunctionDef`` -structure with the ``METH_ARG0_FUNCTION`` flag set. -The C function then calls ``__func__`` with the correct arguments. -For methods which bind instances of ``basefunction`` -(more precisely, which have the ``Py_TPFLAGS_BASEFUNCTION`` flag set) -that have ``m_self == NULL``, -we instead use the ``PyCFunctionDef`` from the original function. -In this case, the ``__func__`` attribute is only used to implement various attributes -but not for calling the method. +- For arbitrary callables, we use a single fixed ``PyCFunctionDef`` + structure with the ``METH_ARG0_FUNCTION`` flag set. + The C function then calls ``__func__`` with the correct arguments. -When constructing a new method from a ``basefunction``, +- For methods which bind instances of ``base_function`` + (more precisely, which have the ``Py_TPFLAGS_BASEFUNCTION`` flag set) + that allow self slicing, + we instead use the ``PyCFunctionDef`` from the original function. + In this case, the ``__func__`` attribute is only used to implement + various attributes but not for calling the method. + +When constructing a new method from a ``base_function``, we check that the ``self`` object is an instance of ``__objclass__`` (if such a class was specified) and raise a ``TypeError`` otherwise. The C structure is:: + PyTypeObject PyMethod_Type; + typedef struct { PyBaseFunctionObject base; PyObject *im_func; /* __func__: function implementing the method; readonly */ @@ -293,16 +305,16 @@ The C structure is:: -Calling basefunction instances -============================== +Calling base_function instances +=============================== -We specify the implementation of ``__call__`` for instances of ``basefunction``. +We specify the implementation of ``__call__`` for instances of ``base_function``. __objclass__ ------------ First of all, if the function has an ``__objclass__`` attribute but -``m_self`` is ``NULL`` (this is the case for non-static unbound methods of extension types), +``m_self`` is ``NULL`` (this is the case for unbound methods of extension types), then the function must be called with at least one positional argument and the first (typically called ``self``) must be an instance of ``__objclass__``. If not, a ``TypeError`` is raised. @@ -311,31 +323,30 @@ Flags ----- For convenience, we define a new constant: -``METH_CALLSIGNATURE`` combines the flags from ``PyCFunctionDef.ml_flags`` +``METH_CALLSIGNATURE`` combines all flags from ``PyCFunctionDef.ml_flags`` which specify the signature of the C function to be called. It is equal to :: - METH_NOARGS | METH_O | METH_VARARGS | METH_FASTCALL | METH_KEYWORDS + METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O | METH_KEYWORDS Exactly one of the first four flags above must be set and only ``METH_VARARGS`` and ``METH_FASTCALL`` may be combined with ``METH_KEYWORDS``. Violating these rules is undefined behaviour. -There are two more flags which affect calling functions: -``METH_ARG0_FUNCTION`` and ``METH_ARG0_NO_SLICE``. - +There is one new flag which affects calling functions, +namely ``METH_ARG0_FUNCTION``. Some flags are already documented in [#methoddoc]_. -We explain the others shortly. +We explain the other two shortly. Self slicing ------------ -If the function has no ``__self__`` -attribute and none of the flags ``METH_ARG0_FUNCTION``, ``METH_ARG0_NO_SLICE`` nor ``METH_STATIC`` is set, +If the function has ``m_self == NULL`` +and the flag ``METH_ARG0_FUNCTION`` is not set, then the first positional argument (if any) is removed from ``*args`` and instead passed as first argument to the C function. Effectively, the first positional argument is treated as ``__self__``. -This process is called "self slicing". +This process is called "self slicing" and is meant to support unbound methods. This does not affect keyword arguments. METH_FASTCALL @@ -364,17 +375,10 @@ METH_ARG0_FUNCTION ------------------ If this flag is set, then the first argument to the C function -is the function itself (the ``basefunction`` instance) instead of ``__self__``. +is the function itself (the ``base_function`` instance) instead of ``m_self``. In this case, the C function should deal with ``__self__`` by getting it from the function, for example using ``PyBaseFunction_GET_SELF``. -METH_ARG0_NO_SLICE ------------------- - -The flag ``METH_ARG0_NO_SLICE`` disables self slicing. -It is not allowed to combine the flags ``METH_ARG0_FUNCTION`` and ``METH_ARG0_NO_SLICE``. -That is not a problem because ``METH_ARG0_FUNCTION`` already disables self slicing. - Automatic creation of built-in functions ======================================== @@ -408,7 +412,7 @@ For the case of functions of a module, An important consequence is that such functions by default do not become methods when used as attribute -(``basefunction.__get__`` only does that if ``__self__`` was unset). +(``base_function.__get__`` only does that if ``m_self`` was ``NULL``). One could consider this a bug, but this was done for backwards compatibility reasons: in an initial post on python-ideas [#proposal]_ the concensus was to keep this misfeature of built-in functions. @@ -425,9 +429,9 @@ New type flag A new ``PyTypeObject`` flag (for ``tp_flags``) is added: ``Py_TPFLAGS_BASEFUNCTION`` to indicate that instances of this type are -functions which can be called as a ``basefunction``. -In other words, subclasses of ``basefunction`` -which follow the implementation from `Calling basefunction instances`_. +functions which can be called as a ``base_function``. +In other words, subclasses of ``base_function`` +which follow the implementation from `Calling base_function instances`_. This is different from flags like ``Py_TPFLAGS_LIST_SUBCLASS`` because it indicates more than just a subclass: @@ -447,7 +451,7 @@ We add and change some Python/C API functions: is an instance of a type with the ``Py_TPFLAGS_BASEFUNCTION`` set. - ``PyObject* PyBaseFunction_New(PyTypeObject *cls, PyCFunctionDef *ml, PyObject *self, PyObject *module, PyTypeObject *objclass)``: - create a new instance of ``cls`` (which must be a subclass of ``basefunction``) + create a new instance of ``cls`` (which must be a subclass of ``base_function``) from the given data. - ``int PyCFunction_Check(PyObject *op)``: return true if ``op`` @@ -456,21 +460,24 @@ We add and change some Python/C API functions: - ``int PyCFunction_NewEx(PyMethodDef* ml, PyObject *self, PyObject* module)``: create a new instance of ``builtin_function``. As special case, if ``self`` is ``NULL``, - then set ``self = Py_None`` instead. - This is done for backwards compatibility. + then set ``self = Py_None`` instead (for backwards compatibility). - ``int PyFunction_Check(PyObject *op)``: return true if ``op`` - is an instance of ``generic_function``. + is an instance of ``defined_function``. + +- ``PyPythonFunction_New(PyTypeObject *cls, PyObject *code, PyObject *globals, PyObject *name, PyObject *qualname)``: + create a new instance of ``cls`` (which must be a sublass of ``python_function``) + from the given data. - ``PyObject* PyFunction_New(PyObject *code, PyObject *globals)``: create a new instance of ``python_function``. -- ``PyObject* PyFunction_NewWithQualName(PyObject *code, PyObject *globals)``: +- ``PyObject* PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname)``: create a new instance of ``python_function``. -- For some existing ``PyCFunction_...`` and ``PyMethod_`` functions, +- For many existing ``PyCFunction_...`` and ``PyMethod_`` functions, we define a new function ``PyBaseFunction_...`` - acting on ``basefunction`` instances. + acting on ``base_function`` instances. For backwards compatibility, the old functions are kept as aliases of the new functions. @@ -478,8 +485,8 @@ Changes to the types module --------------------------- Two types are added: ``types.BaseFunctionType`` corresponding to -``basefunction`` and ``types.GenericFunctionType`` corresponding to -``generic_function``. +``base_function`` and ``types.DefinedFunctionType`` corresponding to +``defined_function``. Apart from that, no changes to the ``types`` module are made. In particular, ``types.FunctionType`` refers to ``python_function``. @@ -490,12 +497,16 @@ as ``types.BuiltinMethodType``. Changes to the inspect module ----------------------------- -``inspect.isbasefunction`` checks for an instance of ``basefunction``. +``inspect.isbasefunction`` checks for an instance of ``base_function``. -``inspect.isfunction`` checks for an instance of ``generic_function``. +``inspect.isfunction`` checks for an instance of ``defined_function``. ``inspect.isbuiltin`` checks for an instance of ``builtin_function``. +``inspect.isroutine`` checks ``isbasefunction`` or ``ismethoddescriptor``. + +Note that bpo-33261 [#bpo33261]_ should be fixed first. + Profiling --------- @@ -528,14 +539,14 @@ Non-CPython implementations =========================== For other implementations of Python apart from CPython, -only the classes ``basefunction``, ``bound_method`` and ``python_function`` are required. +only the classes ``base_function``, ``bound_method`` and ``python_function`` are required. The latter two are the only classes which can be instantiated directly from the Python interpreter. -We require ``basefunction`` for consistency but we put no requirements on it: +We require ``base_function`` for consistency but we put no requirements on it: it is acceptable if this is just a copy of ``object``. Support for the new ``__objclass__`` attribute is not required. -If there is no ``generic_function`` type, -then ``types.GenericFunctionType`` should be an alias of ``types.FunctionType``. +If there is no ``defined_function`` type, +then ``types.DefinedFunctionType`` should be an alias of ``types.FunctionType``. Rationale @@ -544,7 +555,7 @@ Rationale Why not simply change existing classes? --------------------------------------- -One could try to solve the problem not by introducing a new ``basefunction`` +One could try to solve the problem not by introducing a new ``base_function`` class and changing the class hierarchy, but by just changing existing classes. That might look like a simpler solution but it is not: @@ -572,32 +583,32 @@ And even if ``__text_signature__`` would allow arbitrary signatures somehow, that is only one piece of introspection: it does not help with ``inspect.getsourcefile`` for example. -generic_function versus python_function +defined_function versus python_function --------------------------------------- -The names ``generic_function`` and ``python_function`` +The names ``defined_function`` and ``python_function`` were chosen to be different from ``function`` -because none of the two classes ``generic_function``/``python_function`` +because none of the two classes ``defined_function``/``python_function`` is an obvious candidate to receive the ``function`` name. It also allows to use the word "function" informally without referring to a specific class. In many places, a decision needs to be made whether the old ``function`` class -should be replaced by ``generic_function`` or ``python_function``. +should be replaced by ``defined_function`` or ``python_function``. This is done by thinking of the most likely use case: 1. ``types.FunctionType`` refers to ``python_function`` because that type might be used to construct instances using ``types.FunctionType(...)``. -2. ``inspect.isfunction()`` refers to ``generic_function`` +2. ``inspect.isfunction()`` refers to ``defined_function`` because this is the class where introspection is supported. 3. The C API functions ``PyFunction_New...`` refer to ``python_function`` simply because one cannot create instances - of ``generic_function``. + of ``defined_function``. 4. The C API functions ``PyFunction_Check`` and ``PyFunction_Get/Set...`` - refer to ``generic_function`` because all attributes exist for instances of ``generic_function``. + refer to ``defined_function`` because all attributes exist for instances of ``defined_function``. Scope of this PEP: which classes are involved? ---------------------------------------------- @@ -613,7 +624,7 @@ it makes sense to get rid of unbound methods for extension types. For now, no changes are made to the classes ``staticmethod``, ``classmethod`` and ``classmethod_descriptor``. -It would certainly make sense to put these in the ``basefunction`` +It would certainly make sense to put these in the ``base_function`` class hierarchy and unify ``classmethod`` and ``classmethod_descriptor``. However, this PEP is already big enough and this is left as a possible future improvement. @@ -633,14 +644,29 @@ In any case, there is no reason to deal with it in this PEP. It doesn't seem used at all within CPython 3.7, but maybe external packages use it? -__self__ in basefunction ------------------------- +Not treating METH_STATIC and METH_CLASS +--------------------------------------- + +Almost nothing in this PEP refers to the flags ``METH_STATIC`` and ``METH_CLASS``. +These flags are checked only by the `Automatic creation of built-in functions`_. +When a ``staticmethod``, ``classmethod`` or ``classmethod_descriptor`` +is bound (i.e. ``__get__`` is called), +a ``base_function`` instance is created with ``m_self != NULL``. +For a ``classmethod``, this is obvious since ``m_self`` +is the class that the method is bound to. +For a ``staticmethod``, one can take an arbitrary Python object for ``m_self``. +For backwards compatibility, we choose ``m_self = __objclass__`` for static methods +of extension types. + +__self__ in base_function +------------------------- It may look strange at first sight to add the ``__self__`` slot -in ``basefunction`` as opposed to ``bound_method``. +in ``base_function`` as opposed to ``bound_method``. We took this idea from the existing ``builtin_function_or_method`` class. -It allows us to have a single general implementation of ``__call__`` +It allows us to have a single general implementation of ``__call__`` and ``__get__`` for the various function classes discussed in this PEP. + It also makes it easy to support existing built-in functions which set ``__self__`` to the module (for example, ``sys.exit.__self__`` is ``sys``). @@ -671,32 +697,6 @@ Therefore, it should be easy to change existing ``tp_call`` slots to use ``METH_ARG0_FUNCTION``. There is one extra complication though: ``__self__`` must be handled manually. -Self slicing: METH_ARG0_NO_SLICE --------------------------------- - -**TODO**: ``METH_ARG0_NO_SLICE`` will probably be dropped from -the PEP since both ``METH_ARG0_FUNCTION`` and ``METH_STATIC`` -already disable self slicing. - -.. We define "self slicing" to mean slicing off the ``self`` argument of a method - from the ``*args`` tuple when an unbound method is called. - This ``self`` argument is then passed as first argument to the C function. - -.. The specification of ``METH_ARG0_NO_SLICE`` may seem strange at first. - The negation is confusing, but it is done for backwards compatibility: - existing methods require self slicing but do not specify a flag for it. - -.. Since ``METH_ARG0_FUNCTION`` is clearly incompatible with self slicing - (both use the first argument of the C function), - this PEP dictates that ``METH_ARG0_FUNCTION`` disables self slicing. - So one may wonder if there is actually a use case for ``METH_ARG0_NO_SLICE`` - without ``METH_ARG0_FUNCTION``. - If not, then one could simply unify those two flags in one flag - ``METH_ARG0_FUNCTION``. - -.. However, a priori, the flag ``METH_ARG0_NO_SLICE`` is meaningful, - so we keep the two flags ``METH_ARG0_FUNCTION`` and ``METH_ARG0_NO_SLICE`` separate. - User flags: METH_CUSTOM and METH_USRx ------------------------------------- @@ -738,7 +738,7 @@ Built-in bound and unbound methods The types of built-in bound and unbound methods will change. However, this does not affect calling such methods -because the protocol in ``basefunction.__call__`` +because the protocol in ``base_function.__call__`` (in particular the handling of ``__objclass__`` and self slicing) was specifically designed to be backwards compatible. All attributes which existed before (like ``__objclass__`` and ``__self__``) @@ -761,6 +761,13 @@ For example, ``__objclass__`` now appears on bound methods too and all methods get a ``__func__`` attribute. We expect that this will not cause problems. +method_descriptor and PyDescr_NewMethod +--------------------------------------- + +The classes ``method_descriptor`` and the constructor ``PyDescr_NewMethod`` +are deprecated and no longer used by CPython itself. +They are kept for backwards compatibility though. + Reference Implementation ======================== @@ -778,8 +785,8 @@ so feel free to remove this once the PEP has been accepted. For reference, we describe in detail the relevant existing classes in CPython 3.7. -There are a surprisingly large number of classes involved, -each of them is an "orphan" class (no non-trivial subclasses nor superclasses). +Each of the classes involved is an "orphan" class +(no non-trivial subclasses nor superclasses). builtin_function_or_method: built-in functions and bound methods ---------------------------------------------------------------- @@ -890,7 +897,10 @@ References .. [#cython] Cython (http://cython.org/) -.. [#bpo30071] Python bug 30071 (https://bugs.python.org/issue30071) +.. [#bpo30071] Python bug 30071, Duck-typing inspect.isfunction() (https://bugs.python.org/issue30071) + +.. [#bpo33261] Python bug 33261, inspect.isgeneratorfunction fails on hand-created methods + (https://bugs.python.org/issue33261 and https://github.com/python/cpython/pull/6448) .. [#ABI] PEP 384, Defining a Stable ABI, Löwis (https://www.python.org/dev/peps/pep-0384)