import types
import inspect
import keyword
+import builtins
__all__ = ['dataclass',
'field',
# worries about external callers.
if locals is None:
locals = {}
+ # __builtins__ may be the "builtins" module or
+ # the value of its "__dict__",
+ # so make sure "__builtins__" is the module.
+ if globals is not None and '__builtins__' not in globals:
+ globals['__builtins__'] = builtins
return_annotation = ''
if return_type is not MISSING:
locals['_return_type'] = return_type
# self_name is what "self" is called in this function: don't
# hard-code "self", since that might be a field name.
if frozen:
- return f'object.__setattr__({self_name},{name!r},{value})'
+ return f'__builtins__.object.__setattr__({self_name},{name!r},{value})'
return f'{self_name}.{name}={value}'
import pickle
import inspect
+import builtins
import unittest
from unittest.mock import Mock
from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional
first = next(iter(sig.parameters))
self.assertEqual('self', first)
+ def test_field_named_object(self):
+ @dataclass
+ class C:
+ object: str
+ c = C('foo')
+ self.assertEqual(c.object, 'foo')
+
+ def test_field_named_object_frozen(self):
+ @dataclass(frozen=True)
+ class C:
+ object: str
+ c = C('foo')
+ self.assertEqual(c.object, 'foo')
+
+ def test_field_named_like_builtin(self):
+ # Attribute names can shadow built-in names
+ # since code generation is used.
+ # Ensure that this is not happening.
+ exclusions = {'None', 'True', 'False'}
+ builtins_names = sorted(
+ b for b in builtins.__dict__.keys()
+ if not b.startswith('__') and b not in exclusions
+ )
+ attributes = [(name, str) for name in builtins_names]
+ C = make_dataclass('C', attributes)
+
+ c = C(*[name for name in builtins_names])
+
+ for name in builtins_names:
+ self.assertEqual(getattr(c, name), name)
+
+ def test_field_named_like_builtin_frozen(self):
+ # Attribute names can shadow built-in names
+ # since code generation is used.
+ # Ensure that this is not happening
+ # for frozen data classes.
+ exclusions = {'None', 'True', 'False'}
+ builtins_names = sorted(
+ b for b in builtins.__dict__.keys()
+ if not b.startswith('__') and b not in exclusions
+ )
+ attributes = [(name, str) for name in builtins_names]
+ C = make_dataclass('C', attributes, frozen=True)
+
+ c = C(*[name for name in builtins_names])
+
+ for name in builtins_names:
+ self.assertEqual(getattr(c, name), name)
+
def test_0_field_compare(self):
# Ensure that order=False is the default.
@dataclass