@@ -240,11 +240,12 @@ def _get_previous_field_default(node: nodes.ClassDef, name: str) -> nodes.NodeNG
240240 return None
241241
242242
243- def _generate_dataclass_init (
243+ def _generate_dataclass_init ( # pylint: disable=too-many-locals
244244 node : nodes .ClassDef , assigns : list [nodes .AnnAssign ], kw_only_decorated : bool
245245) -> str :
246246 """Return an init method for a dataclass given the targets."""
247247 params : list [str ] = []
248+ kw_only_params : list [str ] = []
248249 assignments : list [str ] = []
249250 assign_names : list [str ] = []
250251
@@ -323,7 +324,22 @@ def _generate_dataclass_init(
323324 if previous_default :
324325 param_str += f" = { previous_default .as_string ()} "
325326
326- params .append (param_str )
327+ # If the field is a kw_only field, we need to add it to the kw_only_params
328+ # This overwrites whether or not the class is kw_only decorated
329+ if is_field :
330+ kw_only = [k for k in value .keywords if k .arg == "kw_only" ] # type: ignore[union-attr]
331+ if kw_only :
332+ if kw_only [0 ].value .bool_value ():
333+ kw_only_params .append (param_str )
334+ else :
335+ params .append (param_str )
336+ continue
337+ # If kw_only decorated, we need to add all parameters to the kw_only_params
338+ if kw_only_decorated :
339+ kw_only_params .append (param_str )
340+ else :
341+ params .append (param_str )
342+
327343 if not init_var :
328344 assignments .append (assignment_str )
329345
@@ -332,21 +348,16 @@ def _generate_dataclass_init(
332348 )
333349
334350 # Construct the new init method paramter string
335- params_string = "self, "
336- if prev_pos_only :
337- params_string += prev_pos_only
338- if not kw_only_decorated :
339- params_string += ", " .join (params )
340-
351+ # First we do the positional only parameters, making sure to add the
352+ # the self parameter and the comma to allow adding keyword only parameters
353+ params_string = f"self, { prev_pos_only } { ', ' .join (params )} "
341354 if not params_string .endswith (", " ):
342355 params_string += ", "
343356
344- if prev_kw_only :
345- params_string += "*, " + prev_kw_only
346- if kw_only_decorated :
347- params_string += ", " .join (params ) + ", "
348- elif kw_only_decorated :
349- params_string += "*, " + ", " .join (params ) + ", "
357+ # Then we add the keyword only parameters
358+ if prev_kw_only or kw_only_params :
359+ params_string += "*, "
360+ params_string += f"{ prev_kw_only } { ', ' .join (kw_only_params )} "
350361
351362 assignments_string = "\n " .join (assignments ) if assignments else "pass"
352363 return f"def __init__({ params_string } ) -> None:\n { assignments_string } "
0 commit comments