Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions Lib/dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -1233,14 +1233,12 @@ class C(Base):

if namespace is None:
namespace = {}
else:
# Copy namespace since we're going to mutate it.
namespace = namespace.copy()

# While we're looking through the field names, validate that they
# are identifiers, are not keywords, and not duplicates.
seen = set()
anns = {}
annotations = {}
defaults = {}
for item in fields:
if isinstance(item, str):
name = item
Expand All @@ -1249,7 +1247,7 @@ class C(Base):
name, tp, = item
elif len(item) == 3:
name, tp, spec = item
namespace[name] = spec
defaults[name] = spec
else:
raise TypeError(f'Invalid field: {item!r}')

Expand All @@ -1261,12 +1259,19 @@ class C(Base):
raise TypeError(f'Field name duplicated: {name!r}')

seen.add(name)
anns[name] = tp
annotations[name] = tp

# Update 'ns' with the user-supplied namespace plus our calculated values.
def exec_body_callback(ns):
ns.update(namespace)
ns.update(defaults)
ns['__annotations__'] = annotations

namespace['__annotations__'] = anns
# We use `types.new_class()` instead of simply `type()` to allow dynamic creation
# of generic dataclassses.
cls = types.new_class(cls_name, bases, {}, lambda ns: ns.update(namespace))
cls = types.new_class(cls_name, bases, {}, exec_body_callback)

# Apply the normal decorator.
return dataclass(cls, init=init, repr=repr, eq=eq, order=order,
unsafe_hash=unsafe_hash, frozen=frozen,
match_args=match_args)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Remove an unneeded copy of the namespace passed to
dataclasses.make_dataclass().