bpo-28869: Set class module to caller module in ABCMeta.new by alegonz · Pull Request #14126 · python/cpython (original) (raw)

Hello, this is a PR to the bug reported in bpo-28869 (https://bugs.python.org/issue28869).

Issues:

Solution:

If the __module__ variable is not found in the namespace variable, inspect and use the module of the caller. This follows the same pattern used in namedtuple. Values set via __init_subclass__ take precedence.

There were concerns that inspection might slow down further ABCs creation, so I also did some benchmarking and got these results:

C implementation
    Absolute difference: 0.00115500006359 ms
    Slowdown: 4.61538495086 %
Py implementation
    Absolute difference: 0.00129000000015 ms
    Slowdown: 3.67301613313 %

Notes:

Is 3~5% considered a significant drop in performance?

I temporarily commited the script for benchmarking in the root directory for sharing purposes. This will be removed in a future commit.

Also, following the discussion in the bpo thread regarding the pickle documentation, since this issue is not limited to ABCMeta, I propose to add the following paragraph (highlighted in bold) in the "What can be pickled and unpickled?" section:

...
Note that functions (built-in and user-defined) are pickled by "fully qualified"
name reference, not by value. [2] This means that only the function name is
pickled, along with the name of the module the function is defined in. Neither
the function's code, nor any of its function attributes are pickled. Thus the
defining module must be importable in the unpickling environment, and the module
must contain the named object, otherwise an exception will be raised. [3]

When pickling instances of classes defined dynamically (i.e. classes defined by calling type() (or any other metaclass) directly) you might need to set the __module__ attribute of the class to the module where the class was defined in. This is the case when the class creation and the call to type() reside in different modules.

Would this be an appropriate explanation?

https://bugs.python.org/issue28869