This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: ABCMeta classes do not support the **kwargs standard class interface
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.2, Python 3.3, Python 3.4, Python 3.5
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: r.david.murray, trcarden, yselivanov
Priority: normal Keywords:

Created on 2015-05-13 23:46 by trcarden, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
abc_meta.py trcarden, 2015-05-13 23:46 Test file showing problem
Messages (6)
msg243130 - (view) Author: Timothy Cardenas (trcarden) Date: 2015-05-13 23:46
Summary:
Any class that derives from the ABCMeta class doesn't support keyword variable arguments as defined here :https://www.python.org/dev/peps/pep-3115/. 


Expected:
If i define a simple class that derives from ABCMeta that has a kwarg the class should be created (see below

from collections import UserDict
class MyDict(UserDict, bar='baz'):
    pass
dictionary = MyDict()  # Expect this to create a new instance of MyDict.


Actual:

from collections import UserDict
class MyDict(UserDict, bar='baz'):
    pass
dictionary = MyDict()  # This call fails because UserDict inherits from ABCMeta

Traceback (most recent call last):
  File "abc_meta.py", line 4, in <module>
    class MyDict(UserDict, bar='baz'):
msg243131 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2015-05-13 23:56
ABCMeta does not support arbitrary keyword arguments, that is correct.  If you want keyword arguments to be handled, you need to write your own metaclass that does so.

(I'm pretty sure I'm reading the PEP correctly...if not I'm sure one of the other core devs will re-open this ;)
msg243133 - (view) Author: Timothy Cardenas (trcarden) Date: 2015-05-14 00:34
Hmm Ok. You are right i can do the following:

from collections import UserDict
from abc import ABCMeta


class MetaMyDict(ABCMeta):

    @classmethod
    def __prepare__(cls, name, bases, **kwargs):
        return {}

    def __new__(mcls, name, bases, namespace, **kwds):
        return super().__new__(mcls, name, bases, namespace)

    def __init__(cls, name, bases, namespace, **kargs):
        return super().__init__(name, bases, namespace)

class MyDict(UserDict, metaclass=MetaMyDict, bar='baz'):
    pass

dictionary = MyDict()

But I guess i would have expected a core lib library to be consistent with the data model https://docs.python.org/3.4/reference/datamodel.html#preparing-the-class-namespace. As it stands an end user can't get a subclass of ABCMeta to work with the same **kwargs interface without creating a custom metaclass that strips it out before passing to ABCMeta. 

Wouldn't it be much easier and technically correct for the core ABCMeta library to adopt the same interface contract for class creation introduced in python3?
msg243138 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2015-05-14 01:29
> Wouldn't it be much easier and technically correct for the core ABCMeta library to adopt the same interface contract for class creation introduced in python3?

No, it would not be technically correct.  For the same reason, object.__init__ does not accept any parameters.
msg243139 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2015-05-14 01:38
Yes, this is exactly analogous to object.__init__ not accepting arguments, but subclasses being free to do so.  ABCMeta *does* adopt the contract.  keyword arguments to the class constructor are not accepted unless you write a meta class that accepts them.  Period.  (That is, "class Foo(bar='baz'): pass" fails.)
msg243142 - (view) Author: Timothy Cardenas (trcarden) Date: 2015-05-14 02:27
Ahhh i see now. 

Even the simple case "class Foo(bar='baz'): pass" fails.

I misunderstood the documentation then. I thought that python 3 introduced a new interface for all classes when it actually just introduced the option to add keyword arguments to your own metaclasses but didn't alter the base level class interface.

I wanted a bit more background around the object.__init__ and found this ticket: http://bugs.python.org/issue1683368. While this is probably not the only place where this comes up I see the tact that the python core team took and understand your reference more completely now.

I thank both of you for your help and quick responses.
History
Date User Action Args
2022-04-11 14:58:16adminsetgithub: 68371
2015-05-14 02:27:36trcardensetmessages: + msg243142
2015-05-14 01:38:03r.david.murraysetmessages: + msg243139
2015-05-14 01:29:19yselivanovsetstatus: open -> closed

nosy: + yselivanov
messages: + msg243138

resolution: remind -> not a bug
2015-05-14 00:34:22trcardensetstatus: closed -> open
resolution: not a bug -> remind
messages: + msg243133
2015-05-13 23:56:38r.david.murraysetstatus: open -> closed

nosy: + r.david.murray
messages: + msg243131

resolution: not a bug
stage: resolved
2015-05-13 23:46:32trcardencreate