diff options
author | Vadim Pushtaev <pushtaev.vm@gmail.com> | 2018-08-12 11:46:05 (GMT) |
---|---|---|
committer | Eric V. Smith <ericvsmith@users.noreply.github.com> | 2018-08-12 11:46:05 (GMT) |
commit | 4d12e4dc28b7c782c368bae2e8fd3815167ed37d (patch) | |
tree | 27d658c85e655c7a59a2de0d382d6e9d58a04365 | |
parent | 65b5ef02ec1f44e3a19b689a1ecf73d01c82161b (diff) | |
download | cpython-4d12e4dc28b7c782c368bae2e8fd3815167ed37d.zip cpython-4d12e4dc28b7c782c368bae2e8fd3815167ed37d.tar.gz cpython-4d12e4dc28b7c782c368bae2e8fd3815167ed37d.tar.bz2 |
bpo-34213: Allow dataclasses to work with a field named 'object'. (GH-8452)
-rw-r--r-- | Lib/dataclasses.py | 8 | ||||
-rwxr-xr-x | Lib/test/test_dataclasses.py | 50 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2018-07-25-00-40-14.bpo-34213.O15MgP.rst | 1 |
3 files changed, 58 insertions, 1 deletions
diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index e00a125..a43d076 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -4,6 +4,7 @@ import copy import types import inspect import keyword +import builtins __all__ = ['dataclass', 'field', @@ -343,6 +344,11 @@ def _create_fn(name, args, body, *, globals=None, locals=None, # 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 @@ -365,7 +371,7 @@ def _field_assign(frozen, name, value, self_name): # 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}' diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index c5140e8..4c93513 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -6,6 +6,7 @@ from dataclasses import * 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 @@ -192,6 +193,55 @@ class TestCase(unittest.TestCase): 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 diff --git a/Misc/NEWS.d/next/Library/2018-07-25-00-40-14.bpo-34213.O15MgP.rst b/Misc/NEWS.d/next/Library/2018-07-25-00-40-14.bpo-34213.O15MgP.rst new file mode 100644 index 0000000..28012af --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-07-25-00-40-14.bpo-34213.O15MgP.rst @@ -0,0 +1 @@ +Allow frozen dataclasses to have a field named "object". Previously this conflicted with an internal use of "object". |