summaryrefslogtreecommitdiffstats
path: root/Lib/dataclasses.py
diff options
context:
space:
mode:
authorEric V. Smith <ericvsmith@users.noreply.github.com>2018-05-16 15:31:29 (GMT)
committerGitHub <noreply@github.com>2018-05-16 15:31:29 (GMT)
commit4e81296b1874829912c687eba4d39361ab51e145 (patch)
tree46db8179f7b5f6eccd66a688ef4126cc34457b38 /Lib/dataclasses.py
parent5db5c0669e624767375593cc1a01f32092c91c58 (diff)
downloadcpython-4e81296b1874829912c687eba4d39361ab51e145.zip
cpython-4e81296b1874829912c687eba4d39361ab51e145.tar.gz
cpython-4e81296b1874829912c687eba4d39361ab51e145.tar.bz2
bpo-33536: Validate make_dataclass() field names. (GH-6906)
Diffstat (limited to 'Lib/dataclasses.py')
-rw-r--r--Lib/dataclasses.py15
1 files changed, 15 insertions, 0 deletions
diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py
index bb77d3b..2c5593b 100644
--- a/Lib/dataclasses.py
+++ b/Lib/dataclasses.py
@@ -3,6 +3,7 @@ import sys
import copy
import types
import inspect
+import keyword
__all__ = ['dataclass',
'field',
@@ -1100,6 +1101,9 @@ def make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True,
# 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 = {}
for item in fields:
if isinstance(item, str):
@@ -1110,6 +1114,17 @@ def make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True,
elif len(item) == 3:
name, tp, spec = item
namespace[name] = spec
+ else:
+ raise TypeError(f'Invalid field: {item!r}')
+
+ if not isinstance(name, str) or not name.isidentifier():
+ raise TypeError(f'Field names must be valid identifers: {name!r}')
+ if keyword.iskeyword(name):
+ raise TypeError(f'Field names must not be keywords: {name!r}')
+ if name in seen:
+ raise TypeError(f'Field name duplicated: {name!r}')
+
+ seen.add(name)
anns[name] = tp
namespace['__annotations__'] = anns