code: def _create_pandas_udf(f, returnType, evalType):
      argspec = getfullargspec(f)
  
      # pandas UDF by type hints.
      if evalType in [
          PythonEvalType.SQL_SCALAR_PANDAS_UDF,
          PythonEvalType.SQL_SCALAR_PANDAS_ITER_UDF,
          PythonEvalType.SQL_GROUPED_AGG_PANDAS_UDF,
      ]:
          warnings.warn(
              "In Python 3.6+ and Spark 3.0+, it is preferred to specify type hints for "
              "pandas UDF instead of specifying pandas UDF type which will be deprecated "
              "in the future releases. See SPARK-28264 for more details.",
              UserWarning,
          )
      elif evalType in [
          PythonEvalType.SQL_GROUPED_MAP_PANDAS_UDF,
          PythonEvalType.SQL_MAP_PANDAS_ITER_UDF,
          PythonEvalType.SQL_MAP_ARROW_ITER_UDF,
          PythonEvalType.SQL_COGROUPED_MAP_PANDAS_UDF,
          PythonEvalType.SQL_GROUPED_MAP_PANDAS_UDF_WITH_STATE,
          PythonEvalType.SQL_GROUPED_MAP_ARROW_UDF,
          PythonEvalType.SQL_COGROUPED_MAP_ARROW_UDF,
          PythonEvalType.SQL_ARROW_BATCHED_UDF,
      ]:
          # In case of 'SQL_GROUPED_MAP_PANDAS_UDF', deprecation warning is being triggered
          # at `apply` instead.
          # In case of 'SQL_MAP_PANDAS_ITER_UDF', 'SQL_MAP_ARROW_ITER_UDF' and
          # 'SQL_COGROUPED_MAP_PANDAS_UDF', the evaluation type will always be set.
          # In case of 'SQL_ARROW_BATCHED_UDF', no deprecation warning is required since it is not
          # exposed to users.
          pass
      elif len(argspec.annotations) > 0:
          try:
              type_hints = get_type_hints(f)
          except NameError:
              type_hints = {}
          evalType = infer_eval_type(signature(f), type_hints)
          assert evalType is not None
  
      if evalType is None:
          # Set default is scalar UDF.
          evalType = PythonEvalType.SQL_SCALAR_PANDAS_UDF
  
      if (
          (
              evalType == PythonEvalType.SQL_SCALAR_PANDAS_UDF
              or evalType == PythonEvalType.SQL_SCALAR_PANDAS_ITER_UDF
          )
          and len(argspec.args) == 0
          and argspec.varargs is None
      ):
          raise PySparkValueError(
              error_class="INVALID_PANDAS_UDF",
              message_parameters={
                  "detail": "0-arg pandas_udfs are not supported. "
                  "Instead, create a 1-arg pandas_udf and ignore the arg in your function.",
              },
          )
  
      if evalType == PythonEvalType.SQL_GROUPED_MAP_PANDAS_UDF and len(
          argspec.args
      ) not in (1, 2):
          raise PySparkValueError(
              error_class="INVALID_PANDAS_UDF",
              message_parameters={
                  "detail": "pandas_udf with function type GROUPED_MAP or the function in "
                  "groupby.applyInPandas must take either one argument (data) or "
                  "two arguments (key, data).",
              },
          )
  
      if evalType == PythonEvalType.SQL_GROUPED_MAP_ARROW_UDF and len(
          argspec.args
      ) not in (1, 2):
          raise PySparkValueError(
              error_class="INVALID_PANDAS_UDF",
              message_parameters={
                  "detail": "the function in groupby.applyInArrow must take either one argument "
                  "(data) or two arguments (key, data).",
              },
          )
  
      if (
          evalType == PythonEvalType.SQL_COGROUPED_MAP_PANDAS_UDF
          and len(argspec.args) not in (2, 3)
      ):
          raise PySparkValueError(
              error_class="INVALID_PANDAS_UDF",
              message_parameters={
                  "detail": "the function in cogroup.applyInPandas must take either two arguments "
                  "(left, right) or three arguments (key, left, right).",
              },
          )
  
      if evalType == PythonEvalType.SQL_COGROUPED_MAP_ARROW_UDF and len(
          argspec.args
      ) not in (2, 3):
          raise PySparkValueError(
              error_class="INVALID_PANDAS_UDF",
              message_parameters={
                  "detail": "the function in cogroup.applyInArrow must take either two arguments "
                  "(left, right) or three arguments (key, left, right).",
              },
          )
  
      if is_remote():
          from pyspark.sql.connect.udf import (
              _create_udf as _create_connect_udf,
          )
  
          return _create_connect_udf(f, returnType, evalType)
      else:
          return _create_udf(f, returnType, evalType)
  
file_path: spark/python/pyspark/sql/pandas/functions.py
imports: import functools
  import warnings
  from inspect import getfullargspec, signature
  from typing import get_type_hints
  from pyspark.rdd import PythonEvalType
  from pyspark.sql.pandas.typehints import infer_eval_type
  from pyspark.sql.pandas.utils import require_minimum_pandas_version, require_minimum_pyarrow_version
  from pyspark.sql.types import DataType
  from pyspark.sql.udf import _create_udf
  from pyspark.sql.utils import is_remote
  from pyspark.errors import PySparkTypeError, PySparkValueError
label_desc: Use image node_id 2 for calling a global function with example usage: _create_pandas_udf(f, returnType, evalType) and returns: _create_connect_udf, _create_udf