summaryrefslogtreecommitdiff
path: root/astroid/brain
diff options
context:
space:
mode:
authorDaniël van Noord <13665637+DanielNoord@users.noreply.github.com>2022-12-07 21:23:32 +0100
committerDaniël van Noord <13665637+DanielNoord@users.noreply.github.com>2022-12-27 00:33:22 +0100
commit406dfbc8199e6c432c5032059fa82d76d4848cbc (patch)
treeed2947981c43e726a02040d411195a8c89c4bfa9 /astroid/brain
parenta17835335cd1754e3d057e7e326e78e546843f0f (diff)
downloadastroid-git-406dfbc8199e6c432c5032059fa82d76d4848cbc.tar.gz
Handle kw_only=True in dataclass fields
Diffstat (limited to 'astroid/brain')
-rw-r--r--astroid/brain/brain_dataclasses.py39
1 files changed, 25 insertions, 14 deletions
diff --git a/astroid/brain/brain_dataclasses.py b/astroid/brain/brain_dataclasses.py
index 95da7c87..c54c2931 100644
--- a/astroid/brain/brain_dataclasses.py
+++ b/astroid/brain/brain_dataclasses.py
@@ -240,11 +240,12 @@ def _get_previous_field_default(node: nodes.ClassDef, name: str) -> nodes.NodeNG
return None
-def _generate_dataclass_init(
+def _generate_dataclass_init( # pylint: disable=too-many-locals
node: nodes.ClassDef, assigns: list[nodes.AnnAssign], kw_only_decorated: bool
) -> str:
"""Return an init method for a dataclass given the targets."""
params: list[str] = []
+ kw_only_params: list[str] = []
assignments: list[str] = []
assign_names: list[str] = []
@@ -323,7 +324,22 @@ def _generate_dataclass_init(
if previous_default:
param_str += f" = {previous_default.as_string()}"
- params.append(param_str)
+ # If the field is a kw_only field, we need to add it to the kw_only_params
+ # This overwrites whether or not the class is kw_only decorated
+ if is_field:
+ kw_only = [k for k in value.keywords if k.arg == "kw_only"] # type: ignore[union-attr]
+ if kw_only:
+ if kw_only[0].value.bool_value():
+ kw_only_params.append(param_str)
+ else:
+ params.append(param_str)
+ continue
+ # If kw_only decorated, we need to add all parameters to the kw_only_params
+ if kw_only_decorated:
+ kw_only_params.append(param_str)
+ else:
+ params.append(param_str)
+
if not init_var:
assignments.append(assignment_str)
@@ -332,21 +348,16 @@ def _generate_dataclass_init(
)
# Construct the new init method paramter string
- params_string = "self, "
- if prev_pos_only:
- params_string += prev_pos_only
- if not kw_only_decorated:
- params_string += ", ".join(params)
-
+ # First we do the positional only parameters, making sure to add the
+ # the self parameter and the comma to allow adding keyword only parameters
+ params_string = f"self, {prev_pos_only}{', '.join(params)}"
if not params_string.endswith(", "):
params_string += ", "
- if prev_kw_only:
- params_string += "*, " + prev_kw_only
- if kw_only_decorated:
- params_string += ", ".join(params) + ", "
- elif kw_only_decorated:
- params_string += "*, " + ", ".join(params) + ", "
+ # Then we add the keyword only parameters
+ if prev_kw_only or kw_only_params:
+ params_string += "*, "
+ params_string += f"{prev_kw_only}{', '.join(kw_only_params)}"
assignments_string = "\n ".join(assignments) if assignments else "pass"
return f"def __init__({params_string}) -> None:\n {assignments_string}"