Skip to content

Commit

Permalink
Adds reserved word check to signature generation logic. (#4012)
Browse files Browse the repository at this point in the history
* Adds reserved word check to signature generation logic.

* Improve documentation.
  • Loading branch information
strue36 committed Aug 8, 2022
1 parent c356011 commit 4d87699
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 2 deletions.
1 change: 1 addition & 0 deletions changes/4011-strue36.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Adds reserved word check to signature generation logic.
15 changes: 13 additions & 2 deletions pydantic/utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import keyword
import warnings
import weakref
from collections import OrderedDict, defaultdict, deque
Expand Down Expand Up @@ -59,6 +60,7 @@
'lenient_isinstance',
'lenient_issubclass',
'in_ipython',
'is_valid_identifier',
'deep_update',
'update_not_none',
'almost_equal_floats',
Expand Down Expand Up @@ -196,6 +198,15 @@ def in_ipython() -> bool:
return True


def is_valid_identifier(identifier: str) -> bool:
"""
Checks that a string is a valid identifier and not a Python keyword.
:param identifier: The identifier to test.
:return: True if the identifier is valid.
"""
return identifier.isidentifier() and not keyword.iskeyword(identifier)


KeyType = TypeVar('KeyType')


Expand Down Expand Up @@ -248,8 +259,8 @@ def generate_model_signature(
param_name = field.alias
if field_name in merged_params or param_name in merged_params:
continue
elif not param_name.isidentifier():
if allow_names and field_name.isidentifier():
elif not is_valid_identifier(param_name):
if allow_names and is_valid_identifier(field_name):
param_name = field_name
else:
use_var_kw = True
Expand Down
10 changes: 10 additions & 0 deletions tests/test_model_signature.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,16 @@ class Config:
assert _equals(str(signature(Foo)), '(*, foo: str) -> None')


def test_does_not_use_reserved_word():
class Foo(BaseModel):
from_: str = Field(..., alias='from')

class Config:
allow_population_by_field_name = True

assert _equals(str(signature(Foo)), '(*, from_: str) -> None')


def test_extra_allow_no_conflict():
class Model(BaseModel):
spam: str
Expand Down

0 comments on commit 4d87699

Please sign in to comment.