Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion conda/environments/all_cuda-129_arch-aarch64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ dependencies:
- polars>=1.35,<1.45
- pre-commit
- psutil
- pyarrow>=19.0.0,<26.0.0
- pyarrow>=19.0.0
- pytables
- pytest-benchmark
- pytest-cases>=3.8.2
Expand Down
2 changes: 1 addition & 1 deletion conda/environments/all_cuda-129_arch-x86_64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ dependencies:
- polars>=1.35,<1.45
- pre-commit
- psutil
- pyarrow>=19.0.0,<26.0.0
- pyarrow>=19.0.0
- pytables
- pytest-benchmark
- pytest-cases>=3.8.2
Expand Down
2 changes: 1 addition & 1 deletion conda/environments/all_cuda-133_arch-aarch64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ dependencies:
- polars>=1.35,<1.45
- pre-commit
- psutil
- pyarrow>=19.0.0,<26.0.0
- pyarrow>=19.0.0
- pytables
- pytest-benchmark
- pytest-cases>=3.8.2
Expand Down
2 changes: 1 addition & 1 deletion conda/environments/all_cuda-133_arch-x86_64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ dependencies:
- polars>=1.35,<1.45
- pre-commit
- psutil
- pyarrow>=19.0.0,<26.0.0
- pyarrow>=19.0.0
- pytables
- pytest-benchmark
- pytest-cases>=3.8.2
Expand Down
2 changes: 1 addition & 1 deletion conda/recipes/cudf/recipe.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ requirements:
- numba-cuda-mlir >=0.3.0
- numba >=0.60.0,<0.65.0
- numpy >=2.0,<3.0
- pyarrow>=19.0.0,<26.0.0
- pyarrow>=19.0.0
- libcudf =${{ version }}
- pylibcudf =${{ version }}
- ${{ pin_compatible("rmm", upper_bound="x.x") }}
Expand Down
2 changes: 1 addition & 1 deletion conda/recipes/pylibcudf/recipe.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ requirements:
- nvtx >=0.2.1
run_constraints:
- numpy >=2.0,<3.0
- pyarrow>=19.0.0,<26.0.0
- pyarrow>=19.0.0
ignore_run_exports:
from_package:
- cuda-cudart-dev
Expand Down
4 changes: 2 additions & 2 deletions dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -828,10 +828,10 @@ dependencies:
common:
- output_types: [conda]
packages:
- pyarrow>=19.0.0,<26.0.0
- pyarrow>=19.0.0
- output_types: [requirements, constraints, pyproject]
packages:
- pyarrow>=19.0.0,<26.0.0
- pyarrow>=19.0.0
# 'cuda_version' intentionally does not contain fallback entries... we want
# a loud error if an unsupported 'cuda' value is passed
cuda_version:
Expand Down
4 changes: 3 additions & 1 deletion python/cudf/cudf/core/_compat.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION.
# SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

import pandas as pd
import pyarrow as pa
from packaging import version

PANDAS_CURRENT_SUPPORTED_VERSION = version.parse("3.0.2")
PANDAS_VERSION = version.parse(pd.__version__)
PYARROW_GE_26 = version.parse(pa.__version__) >= version.parse("26.0.0")
54 changes: 51 additions & 3 deletions python/cudf/cudf/io/parquet.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from pylibcudf import expressions as plc_expr

from cudf.api.types import is_list_like
from cudf.core._compat import PYARROW_GE_26
from cudf.core.column import (
ColumnBase,
access_columns,
Expand Down Expand Up @@ -1395,11 +1396,14 @@ def _read_parquet(
nrows = -1
if skip_rows is None:
skip_rows = 0
empty_columns = columns is not None and len(columns) == 0
if get_option("io.parquet.low_memory"):
# If filters are used, we can't rely on a RangeIndex
# (row count may be reduced)
allow_range_index = (
filters is None and columns is not None and len(columns) != 0
filters is None
and columns is not None
and (len(columns) != 0 or PYARROW_GE_26)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
)

options = (
Expand Down Expand Up @@ -1465,10 +1469,23 @@ def _read_parquet(
nrows=nrows,
skip_rows=skip_rows,
)
if (
empty_columns
and PYARROW_GE_26
and filters is None
and len(df.index) == 0
):
df.index = RangeIndex(
_num_rows(
filepaths_or_buffers, row_groups, skip_rows, nrows
)
)
return df
else:
allow_range_index = True
if columns is not None and len(columns) == 0 or filters:
if (
columns is not None and len(columns) == 0 and not PYARROW_GE_26
) or filters:
allow_range_index = False

options = (
Expand Down Expand Up @@ -1505,6 +1522,17 @@ def _read_parquet(
nrows=nrows,
skip_rows=skip_rows,
)
if (
empty_columns
and PYARROW_GE_26
and filters is None
and len(df.index) == 0
):
df.index = RangeIndex(
_num_rows(
filepaths_or_buffers, row_groups, skip_rows, nrows
)
)
return df
else:
if (
Expand Down Expand Up @@ -2479,6 +2507,26 @@ def _get_stat_freq(
return result


def _num_rows(
filepaths_or_buffers, row_groups, skip_rows: int, nrows: int
) -> int:
metadata = plc.io.parquet_metadata.read_parquet_metadata(
plc.io.SourceInfo(filepaths_or_buffers)
)
if row_groups is not None:
row_group_rows = metadata.rowgroup_metadata()
file_offsets = itertools.accumulate(
metadata.num_rowgroups_per_file(), initial=0
)
return sum(
row_group_rows[offset + row_group]["num_rows"]
for offset, groups in zip(file_offsets, row_groups, strict=False)
for row_group in groups
)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
num_rows = max(metadata.num_rows() - skip_rows, 0)
return num_rows if nrows < 0 else min(num_rows, nrows)


def _process_metadata(
df: DataFrame,
names: Sequence[Hashable],
Expand Down Expand Up @@ -2592,7 +2640,7 @@ def _process_metadata(
start = range_index_meta["start"] + skip_rows # type: ignore[operator]
stop = int(range_index_meta["stop"]) # type: ignore[arg-type]
if nrows > -1:
stop = start + nrows
stop = min(stop, start + nrows)
idx = RangeIndex(
start=start,
stop=stop,
Expand Down
44 changes: 44 additions & 0 deletions python/cudf/cudf/tests/input_output/test_parquet.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from pyarrow import parquet as pq

import cudf
from cudf.core._compat import PYARROW_GE_26
from cudf.io.parquet import (
ParquetDatasetWriter,
ParquetWriter,
Expand Down Expand Up @@ -3427,6 +3428,49 @@ def test_parquet_columns_and_range_index(columns):
assert_eq(expected, got, check_index_type=True)


@pytest.mark.parametrize("low_memory", [True, False])
@pytest.mark.parametrize("index", [True, False, None])
@pytest.mark.parametrize(
"kwargs, num_rows",
[
({}, 12),
({"skip_rows": 3}, 9),
({"nrows": 5}, 5),
({"nrows": 15}, 12),
({"skip_rows": 3, "nrows": 5}, 5),
({"row_groups": [[0, 2], [1]]}, 6),
],
)
def test_parquet_empty_columns_num_rows(
tmp_path, low_memory, index, kwargs, num_rows
):
paths = []
for i in range(2):
path = str(tmp_path / f"{i}.parquet")
pd.DataFrame({"a": range(6)}).to_parquet(
path, index=index, row_group_size=2
)
paths.append(path)

with cudf.option_context("io.parquet.low_memory", low_memory):
got = cudf.read_parquet(paths, columns=[], **kwargs)

expected_rows = num_rows if index or PYARROW_GE_26 else 0
assert got.shape == (expected_rows, 0)
assert len(got.index) == expected_rows


@pytest.mark.parametrize("low_memory", [True, False])
def test_parquet_empty_columns_nrows_exceeds_num_rows(tmp_path, low_memory):
path = tmp_path / "file.parquet"
pd.DataFrame({"a": range(6)}).to_parquet(path)

with cudf.option_context("io.parquet.low_memory", low_memory):
got = cudf.read_parquet(path, columns=[], nrows=10)

assert got.shape == (6 if PYARROW_GE_26 else 0, 0)


def test_parquet_nested_struct_list():
buffer = BytesIO()
data = {
Expand Down
2 changes: 1 addition & 1 deletion python/cudf/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ dependencies = [
"nvtx>=0.2.1",
"packaging",
"pandas>=3.0.0,<3.1.0",
"pyarrow>=19.0.0,<26.0.0",
"pyarrow>=19.0.0",
"pylibcudf==26.12.*,>=0.0.0a0",
"rich",
"rmm==26.12.*,>=0.0.0a0",
Expand Down
4 changes: 2 additions & 2 deletions python/pylibcudf/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ test = [
"numba-cuda>=0.22.2,<0.31.0",
"numba>=0.60.0,<0.65.0",
"pandas>=3.0.0,<3.1.0",
"pyarrow>=19.0.0,<26.0.0",
"pyarrow>=19.0.0",
"pytest-cov",
"pytest-xdist",
"pytest<9.1.0",
"xxhash",
] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../../dependencies.yaml and run `rapids-dependency-file-generator`.
pyarrow = [
"pyarrow>=19.0.0,<26.0.0",
"pyarrow>=19.0.0",
] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../../dependencies.yaml and run `rapids-dependency-file-generator`.
numpy = [
"numpy>=2.0,<3.0",
Expand Down
Loading