code: def read_parquet(
      path: str,
      columns: Optional[List[str]] = None,
      index_col: Optional[List[str]] = None,
      pandas_metadata: bool = False,
      **options: Any,
  ) -> DataFrame:
      """Load a parquet object from the file path, returning a DataFrame.
  
      Parameters
      ----------
      path : string
          File path
      columns : list, default=None
          If not None, only these columns will be read from the file.
      index_col : str or list of str, optional, default: None
          Index column of table in Spark.
      pandas_metadata : bool, default: False
          If True, try to respect the metadata if the Parquet file is written from pandas.
      options : dict
          All other options passed directly into Spark's data source.
  
      Returns
      -------
      DataFrame
  
      See Also
      --------
      DataFrame.to_parquet
      DataFrame.read_table
      DataFrame.read_delta
      DataFrame.read_spark_io
  
      Examples
      --------
      >>> ps.range(1).to_parquet('%s/read_spark_io/data.parquet' % path)
      >>> ps.read_parquet('%s/read_spark_io/data.parquet' % path, columns=['id'])
         id
      0   0
  
      You can preserve the index in the roundtrip as below.
  
      >>> ps.range(1).to_parquet('%s/read_spark_io/data.parquet' % path, index_col="index")
      >>> ps.read_parquet('%s/read_spark_io/data.parquet' % path, columns=['id'], index_col="index")
      ... # doctest: +NORMALIZE_WHITESPACE
             id
      index
      0       0
      """
      if index_col is None:
          log_advice(
              "If `index_col` is not specified for `read_parquet`, "
              "the default index is attached which can cause additional overhead."
          )
      if (
          "options" in options
          and isinstance(options.get("options"), dict)
          and len(options) == 1
      ):
          options = options.get("options")
  
      if columns is not None:
          columns = list(columns)
  
      index_names = None
  
      if index_col is None and pandas_metadata:
          # Try to read pandas metadata
  
          @pandas_udf(  # type: ignore[call-overload]
              "index_col array<string>, index_names array<string>"
          )
          def read_index_metadata(pser: pd.Series) -> pd.DataFrame:
              binary = pser.iloc[0]
              metadata = pq.ParquetFile(
                  pa.BufferReader(binary)
              ).metadata.metadata
              if b"pandas" in metadata:
                  pandas_metadata = json.loads(
                      metadata[b"pandas"].decode("utf8")
                  )
                  if all(
                      isinstance(col, str)
                      for col in pandas_metadata["index_columns"]
                  ):
                      index_col = []
                      index_names = []
                      for col in pandas_metadata["index_columns"]:
                          index_col.append(col)
                          for column in pandas_metadata["columns"]:
                              if column["field_name"] == col:
                                  index_names.append(column["name"])
                                  break
                          else:
                              index_names.append(None)
                      return pd.DataFrame(
                          {
                              "index_col": [index_col],
                              "index_names": [index_names],
                          }
                      )
              return pd.DataFrame(
                  {"index_col": [None], "index_names": [None]}
              )
  
          index_col, index_names = (
              default_session()
              .read.format("binaryFile")
              .load(path)
              .limit(1)
              .select(
                  read_index_metadata("content").alias("index_metadata")
              )
              .select("index_metadata.*")
              .head()
          )
  
      psdf = read_spark_io(
          path=path,
          format="parquet",
          options=options,
          index_col=index_col,
      )
  
      if columns is not None:
          new_columns = [c for c in columns if c in psdf.columns]
          if len(new_columns) > 0:
              psdf = psdf[new_columns]
          else:
              sdf = default_session().createDataFrame(
                  [], schema=StructType()
              )
              index_spark_columns, index_names = _get_index_map(
                  sdf, index_col
              )
              psdf = DataFrame(
                  InternalFrame(
                      spark_frame=sdf,
                      index_spark_columns=index_spark_columns,
                      index_names=index_names,
                  )
              )
  
      if index_names is not None:
          psdf.index.names = index_names
  
      return psdf
  
imports: from typing import Any, Callable, Dict, List, Optional, Set, Sized, Tuple, Type, Union, cast, no_type_check
  from collections.abc import Iterable
  from datetime import tzinfo
  from functools import reduce
  from io import BytesIO
  import json
  import warnings
  import numpy
  import pandas
  from pandas.api.types import is_datetime64_dtype, is_list_like
  from pandas.tseries.offsets import DateOffset
  import pyarrow
  import pyarrow.parquet
  from pyspark.sql import functions, Column
  from pyspark.sql.functions import pandas_udf
  from pyspark.sql.types import ByteType, ShortType, IntegerType, LongType, FloatType, DoubleType, BooleanType, TimestampType, TimestampNTZType, DecimalType, StringType, DateType, StructType, DataType
  from pyspark.sql.dataframe import DataFrame
  from pyspark import pandas
  from pyspark.pandas._typing import Axis, Dtype, Label, Name
  from pyspark.pandas.base import IndexOpsMixin
  from pyspark.pandas.utils import align_diff_frames, default_session, is_name_like_tuple, is_name_like_value, name_like_string, same_anchor, scol_for, validate_axis, log_advice
  from pyspark.pandas.frame import DataFrame, _reduce_spark_multi
  from pyspark.pandas.internal import InternalFrame, DEFAULT_SERIES_NAME, HIDDEN_COLUMNS, SPARK_INDEX_NAME_FORMAT
  from pyspark.pandas.series import Series, first_series
  from pyspark.pandas.spark.utils import as_nullable_spark_type, force_decimal_precision_scale
  from pyspark.pandas.indexes import Index, DatetimeIndex, TimedeltaIndex
  from pyspark.pandas.indexes.multi import MultiIndex
  from pyspark.sql.utils import get_column_class
label_desc: Use image node_id 8 for calling a global function with example usage: read_parquet(path, columns, index_col, pandas_metadata) and returns: psdf, pd, pd