# Buggy code
def _read_parquet_path(
    session_primitives: "SessionPrimitives",
    path: str,
    columns: Optional[List[str]] = None,
    filters: Optional[Union[List[Tuple[Any]], List[List[Tuple[Any]]]]] = None,
    procs_cpu_bound: Optional[int] = None,
    wait_objects: bool = False,
    wait_objects_timeout: Optional[float] = 10.0,
) -> pd.DataFrame:
    """
    Read parquet data from S3

    :param session_primitives: SessionPrimitives()
    :param path: AWS S3 path (E.g. s3://bucket-name/folder_name/)
    :param columns: Names of columns to read from the file
    :param filters: List of filters to apply, like ``[[('x', '=', 0), ...], ...]``.
    :param procs_cpu_bound: Number of cores used for CPU bound tasks
    :param wait_objects: Wait for all files exists (Not valid when path is a directory) (Useful for eventual consistency situations)
    :param wait_objects: Wait objects Timeout (seconds)
    :return: Pandas DataFrame
    """
    session: Session = session_primitives.session
    if wait_objects is True:
        logger.debug(f"waiting {path}...")
        session.s3.wait_object_exists(path=path, timeout=wait_objects_timeout)
        is_file: bool = True
    else:
        logger.debug(f"checking if {path} exists...")
        is_file = session.s3.does_object_exists(path=path)
        if is_file is False:
            path = path[:-1] if path[-1] == "/" else path
    logger.debug(f"is_file: {is_file}")
    procs_cpu_bound = (
        procs_cpu_bound
        if procs_cpu_bound is not None
        else session_primitives.procs_cpu_bound
        if session_primitives.procs_cpu_bound is not None
        else 1
    )
    use_threads: bool = True if procs_cpu_bound > 1 else False
    logger.debug(f"Reading Parquet: {path}")
    if is_file is True:
        client_s3 = session.boto3_session.client(
            service_name="s3", use_ssl=True, config=session.botocore_config
        )
        bucket, key = path.replace("s3://", "").split("/", 1)
        obj = client_s3.get_object(Bucket=bucket, Key=key)
        table = pq.ParquetFile(source=BytesIO(obj["Body"].read())).read(
            columns=columns, use_threads=use_threads
        )
    else:
        fs: S3FileSystem = get_fs(session_primitives=session_primitives)
        fs = pa.filesystem._ensure_filesystem(fs)
        fs.invalidate_cache()
        table = pq.read_table(
            source=path,
            columns=columns,
            filters=filters,
            filesystem=fs,
            use_threads=use_threads,
        )
    # Check if we lose some integer during the conversion (Happens when has some null value)
    integers = [
        field.name for field in table.schema if str(field.type).startswith("int")
    ]
    logger.debug(f"Converting to Pandas: {path}")
    df = table.to_pandas(use_threads=use_threads, integer_object_nulls=True)
    for c in integers:
        if not str(df[c].dtype).startswith("int"):
            df[c] = df[c].astype("Int64")
    logger.debug(f"Done: {path}")
    return df


# Traceback (KeyError)
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
~/miniconda3/lib/python3.7/site-packages/pandas/core/indexes/base.py in get_loc(self, key, method, tolerance)
2896             try:
-> 2897                 return self._engine.get_loc(key)
2898             except KeyError:

pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_loc()

pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_loc()

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

KeyError: '__index_level_0__'

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
<ipython-input-67-9e66c4b6764b> in <module>
----> 1 wr.pandas.read_parquet(path=PATH)

~/miniconda3/lib/python3.7/site-packages/awswrangler/pandas.py in read_parquet(self, path, columns, filters, procs_cpu_bound, wait_objects, wait_objects_timeout)
1373                                              procs_cpu_bound=procs_cpu_bound,
1374                                              wait_objects=wait_objects,
-> 1375                                              wait_objects_timeout=wait_objects_timeout)
1376         else:
1377             procs = []

~/miniconda3/lib/python3.7/site-packages/awswrangler/pandas.py in _read_parquet_paths(session_primitives, path, columns, filters, procs_cpu_bound, wait_objects, wait_objects_timeout)
1460                 procs_cpu_bound=procs_cpu_bound,
1461                 wait_objects=wait_objects,
-> 1462                 wait_objects_timeout=wait_objects_timeout)
1463             return [df]
1464         else:

~/miniconda3/lib/python3.7/site-packages/awswrangler/pandas.py in _read_parquet_path(session_primitives, path, columns, filters, procs_cpu_bound, wait_objects, wait_objects_timeout)
1524         df = table.to_pandas(use_threads=use_threads, integer_object_nulls=True)
1525         for c in integers:
-> 1526             if not str(df[c].dtype).startswith("int"):
1527                 df[c] = df[c].astype("Int64")
1528         logger.debug(f"Done: {path}")

~/miniconda3/lib/python3.7/site-packages/pandas/core/frame.py in __getitem__(self, key)
2993             if self.columns.nlevels > 1:
2994                 return self._getitem_multilevel(key)
-> 2995             indexer = self.columns.get_loc(key)
2996             if is_integer(indexer):
2997                 indexer = [indexer]

~/miniconda3/lib/python3.7/site-packages/pandas/core/indexes/base.py in get_loc(self, key, method, tolerance)
2897                 return self._engine.get_loc(key)
2898             except KeyError:
-> 2899                 return self._engine.get_loc(self._maybe_cast_indexer(key))
2900         indexer = self.get_indexer([key], method=method, tolerance=tolerance)
2901         if indexer.ndim > 1 or indexer.size > 1:

pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_loc()

pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_loc()

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

KeyError: '__index_level_0__'

# Fixed code
def _read_parquet_path(
    session_primitives: "SessionPrimitives",
    path: str,
    columns: Optional[List[str]] = None,
    filters: Optional[Union[List[Tuple[Any]], List[List[Tuple[Any]]]]] = None,
    procs_cpu_bound: Optional[int] = None,
    wait_objects: bool = False,
    wait_objects_timeout: Optional[float] = 10.0,
) -> pd.DataFrame:
    """
    Read parquet data from S3

    :param session_primitives: SessionPrimitives()
    :param path: AWS S3 path (E.g. s3://bucket-name/folder_name/)
    :param columns: Names of columns to read from the file
    :param filters: List of filters to apply, like ``[[('x', '=', 0), ...], ...]``.
    :param procs_cpu_bound: Number of cores used for CPU bound tasks
    :param wait_objects: Wait for all files exists (Not valid when path is a directory) (Useful for eventual consistency situations)
    :param wait_objects: Wait objects Timeout (seconds)
    :return: Pandas DataFrame
    """
    session: Session = session_primitives.session
    if wait_objects is True:
        logger.debug(f"waiting {path}...")
        session.s3.wait_object_exists(path=path, timeout=wait_objects_timeout)
        is_file: bool = True
    else:
        logger.debug(f"checking if {path} exists...")
        is_file = session.s3.does_object_exists(path=path)
        if is_file is False:
            path = path[:-1] if path[-1] == "/" else path
    logger.debug(f"is_file: {is_file}")
    procs_cpu_bound = (
        procs_cpu_bound
        if procs_cpu_bound is not None
        else session_primitives.procs_cpu_bound
        if session_primitives.procs_cpu_bound is not None
        else 1
    )
    use_threads: bool = True if procs_cpu_bound > 1 else False
    logger.debug(f"Reading Parquet: {path}")
    if is_file is True:
        client_s3 = session.boto3_session.client(
            service_name="s3", use_ssl=True, config=session.botocore_config
        )
        bucket, key = path.replace("s3://", "").split("/", 1)
        obj = client_s3.get_object(Bucket=bucket, Key=key)
        table = pq.ParquetFile(source=BytesIO(obj["Body"].read())).read(
            columns=columns, use_threads=use_threads
        )
    else:
        fs: S3FileSystem = get_fs(session_primitives=session_primitives)
        fs = pa.filesystem._ensure_filesystem(fs)
        fs.invalidate_cache()
        table = pq.read_table(
            source=path,
            columns=columns,
            filters=filters,
            filesystem=fs,
            use_threads=use_threads,
        )
    # Check if we lose some integer during the conversion (Happens when has some null value)
    integers = [
        field.name
        for field in table.schema
        if str(field.type).startswith("int") and field.name != "__index_level_0__"
    ]
    logger.debug(f"Converting to Pandas: {path}")
    df = table.to_pandas(use_threads=use_threads, integer_object_nulls=True)
    logger.debug(f"Casting Int64 columns: {path}")
    for c in integers:
        if not str(df[c].dtype).startswith("int"):
            df[c] = df[c].astype("Int64")
    logger.debug(f"Done: {path}")
    return df