function emitParameterTypeChecks()

in packages/jsii-pacmak/lib/targets/python.ts [3194:3259]


function emitParameterTypeChecks(
  code: CodeMaker,
  context: EmitContext,
  params: readonly string[],
  fqn: string,
): boolean {
  if (!context.runtimeTypeChecking) {
    return false;
  }

  const paramInfo = params.map((param) => {
    const [name] = param.split(/\s*[:=#]\s*/, 1);
    if (name === '*') {
      return { kwargsMark: true };
    } else if (name.startsWith('*')) {
      return { name: name.slice(1), is_rest: true };
    }
    return { name };
  });

  const paramNames = paramInfo
    .filter((param) => param.name != null)
    .map((param) => param.name!.split(/\s*:\s*/)[0]);
  const typesVar = slugifyAsNeeded('type_hints', paramNames);

  let openedBlock = false;
  for (const { is_rest, kwargsMark, name } of paramInfo) {
    if (kwargsMark) {
      if (!context.runtimeTypeCheckKwargs) {
        // This is the keyword-args separator, we won't check keyword arguments here because the kwargs will be rolled
        // up into a struct instance, and that struct's constructor will be checking again...
        break;
      }
      // Skip this (there is nothing to be checked as this is just a marker...)
      continue;
    }

    if (!openedBlock) {
      code.openBlock('if __debug__');
      code.line(
        `${typesVar} = ${context.typeCheckingHelper.getTypeHints(fqn, params)}`,
      );
      openedBlock = true;
    }

    let expectedType = `${typesVar}[${JSON.stringify(name)}]`;
    let comment = '';
    if (is_rest) {
      // This is a vararg, so the value will appear as a tuple.
      expectedType = `typing.Tuple[${expectedType}, ...]`;
      // Need to ignore reportGeneralTypeIssues because pyright incorrectly parses that as a type annotation 😒
      comment = ' # pyright: ignore [reportGeneralTypeIssues]';
    }
    code.line(
      `check_type(argname=${JSON.stringify(
        `argument ${name}`,
      )}, value=${name}, expected_type=${expectedType})${comment}`,
    );
  }
  if (openedBlock) {
    code.closeBlock();
    return true;
  }
  // We did not reference type annotations data if we never opened a type-checking block.
  return false;
}