Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions Lib/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,26 @@ def _m(self): pass

# Provide a PEP 3115 compliant mechanism for class creation
def new_class(name, bases=(), kwds=None, exec_body=None):
"""Create a class object dynamically using the appropriate metaclass."""
"""Create a class object dynamically using the appropriate metaclass.

*name*, *bases*, and *kwds* are the class name, the base classes,
and the keywords of the equivalent class definition (such as
'metaclass'). *kwds* is not a namespace like the third argument
of type(). For example:

new_class('Test', (A, B), {'metaclass': Meta, 'foo': 42})

is equivalent to:

class Test(A, B, metaclass=Meta, foo=42):
pass

To populate the namespace, pass *exec_body*, a callable that takes

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Describe exec_body's argument as a namespace mapping

With a metaclass whose __prepare__ returns a valid non-dict mapping, prepare_class() returns that object and new_class() passes it to exec_body; a mapping need not implement dictionary methods such as .update(), so calling it a “dictionary” can mislead callbacks that use dict-only methods, and the example immediately below uses .update(). Please use “prepared namespace” or “mapping,” as Doc/library/types.rst does.

AGENTS.md reference: AGENTS.md:L14-L14

Useful? React with 👍 / 👎.

the newly created dictionary and populates it. For example:

new_class('C', (MyABC,), {},
exec_body=lambda ns: ns.update(namespace))
"""
resolved_bases = resolve_bases(bases)
meta, ns, kwds = prepare_class(name, resolved_bases, kwds)
if exec_body is not None:
Expand Down Expand Up @@ -123,7 +142,8 @@ def prepare_class(name, bases=(), kwds=None):
*namespace* is the prepared class namespace
*kwds* is an updated copy of the passed in kwds argument with any
'metaclass' entry removed. If no kwds argument is passed in, this will
be an empty dict.
be an empty dict. Passed in keywords are those of the class definition
(such as 'metaclass'), not a class namespace.
"""
if kwds is None:
kwds = {}
Expand Down
Loading