diff options
author | Eric V. Smith <ericvsmith@users.noreply.github.com> | 2018-05-16 15:31:29 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-16 15:31:29 (GMT) |
commit | 4e81296b1874829912c687eba4d39361ab51e145 (patch) | |
tree | 46db8179f7b5f6eccd66a688ef4126cc34457b38 /Lib/dataclasses.py | |
parent | 5db5c0669e624767375593cc1a01f32092c91c58 (diff) | |
download | cpython-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.py | 15 |
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 |