def _generate_signature_parameters(  # noqa: C901 (ignore complexity, could use a refactor)
    init: Callable[..., None],
    fields: dict[str, FieldInfo],
    validate_by_name: bool,
    extra: ExtraValues | None,
) -> dict[str, Parameter]:
    """Generate a mapping of parameter names to Parameter objects for a pydantic BaseModel or dataclass."""
    from itertools import islice

    present_params = signature(init).parameters.values()
    merged_params: dict[str, Parameter] = {}
    var_kw = None
    use_var_kw = False

    for param in islice(present_params, 1, None):  # skip self arg
        # inspect does "clever" things to show annotations as strings because we have
        # `from __future__ import annotations` in main, we don't want that
        if fields.get(param.name):
            # exclude params with init=False
            if getattr(fields[param.name], 'init', True) is False:
                continue
            param = param.replace(name=_field_name_for_signature(param.name, fields[param.name]))
        if param.annotation == 'Any':
            param = param.replace(annotation=Any)
        if param.kind is param.VAR_KEYWORD:
            var_kw = param
            continue
        merged_params[param.name] = param

    if var_kw:  # if custom init has no var_kw, fields which are not declared in it cannot be passed through
        allow_names = validate_by_name
        for field_name, field in fields.items():
            # when alias is a str it should be used for signature generation
            param_name = _field_name_for_signature(field_name, field)

            if field_name in merged_params or param_name in merged_params:
                continue

            if not is_valid_identifier(param_name):
                if allow_names:
                    param_name = field_name
                else:
                    use_var_kw = True
                    continue

            if field.is_required():
                default = Parameter.empty
            elif field.default_factory is not None:
                # Mimics stdlib dataclasses:
                default = _HAS_DEFAULT_FACTORY
            else:
                default = field.default
            merged_params[param_name] = Parameter(
                param_name,
                Parameter.KEYWORD_ONLY,
                annotation=field.rebuild_annotation(),
                default=default,
            )

    if extra == 'allow':
        use_var_kw = True

    if var_kw and use_var_kw:
        # Make sure the parameter for extra kwargs
        # does not have the same name as a field
        default_model_signature = [
            ('self', Parameter.POSITIONAL_ONLY),
            ('data', Parameter.VAR_KEYWORD),
        ]
        if [(p.name, p.kind) for p in present_params] == default_model_signature:
            # if this is the standard model signature, use extra_data as the extra args name
            var_kw_name = 'extra_data'
        else:
            # else start from var_kw
            var_kw_name = var_kw.name

        # generate a name that's definitely unique
        while var_kw_name in fields:
            var_kw_name += '_'
        merged_params[var_kw_name] = var_kw.replace(name=var_kw_name)

    return merged_params
Generate a mapping of parameter names to Parameter objects for a pydantic BaseModel or dataclass.
pydantic/_internal/_signature.py