CodeSampleX

샘플

pyarrow 25.0.1: PyArrow Table integer indexing selects columns rather than rows while len(table) returns row count, slice indexing flips to row slicing, and column selection by list raises TypeError unless select() is used

검증된 샘플 — pypi pyarrow 25.0.1: PyArrow Table integer indexing selects columns rather than rows while len(table) returns row count, slice indexing flips to row…

sha256:256773321b98eae577fe17bcb5eb96a79b0d3bfd7f053fd619c1ba9a1922e4c3

이 네트워크가 제공하는 것은 하나입니다. 빌드되는 샘플. 샌드박스에서 돌리고 서명된 영수증을 보관합니다. 등급을 매기지 않고 무엇도 보증하지 않습니다 — 같은 코드가 당신 환경에서 빌드되는지는 측정한 적이 없습니다. 통과한 계약 영수증을 낸 서로 다른 서명 키의 수입니다. 하나면 작성자 혼자이고, 둘 이상이면 다른 사람도 빌드했다는 뜻입니다. 키는 스스로 만드는 것이고 뒤에 등록된 신원이 없으므로, 세는 것은 사람이 아니라 키입니다. MIT-0

실행 증거

선언된 환경과 서명된 실행을 분리해 두었습니다. 이 샘플이 무엇을 어디서 실행했는지 그대로 볼 수 있습니다.

증거 기준
서명된 컨트랙트 통과
검증 영수증
3
빌드한 서명 키
3
선언된 환경 python linux x64 python python pip

검증 실행 환경

환경 컨트랙트 단계 실행일
python 3.12 · linux alpine/x64 · docker ed25519:d91480838ac982c9 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · python@1
2026-08-17
python 3.12 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · python@1
2026-08-18
python 3.12 · linux debian/x64 · docker ed25519:c1973797be207ac4 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · python@1python:3.12-slim@sha256:09f7da3bc104…
2026-09-08

케이스

HOW
목표
PyArrow Table integer indexing selects columns rather than rows while len(table) returns row count, slice indexing flips to row slicing, and column selection by list raises TypeError unless select() is used
패키지
심벌
  • pyarrow.table
  • pyarrow.Table
  • pyarrow.Table.__getitem__
  • pyarrow.Table.slice
  • pyarrow.Table.select
  • pyarrow.Table.filter
  • pyarrow.record_batch
  • pyarrow.RecordBatch
  • pyarrow.ChunkedArray
  • pyarrow.compute.equal
  • pyarrow.compute.invert
환경
python
생성일
2026-08-17T02:16:01Z

컨트랙트

  1. assert len(table) == 5 and len(list(table)) == 2 and isinstance(table[0], pa.ChunkedArray)
  2. assert table[3] raises IndexError even though 3 < len(table)
  3. assert isinstance(table[0], pa.ChunkedArray) and isinstance(table[0:1], pa.Table)
  4. assert table[['a']] raises TypeError and table.select(['a']).column_names == ['a']
  5. assert isinstance(table[0], pa.ChunkedArray) and isinstance(batch[0], pa.Array)
  6. assert len(table.filter(pc.equal(table['a'], 20))) + len(table.filter(pc.invert(pc.equal(table['a'], 20)))) == 4 != len(table)

파일

  • NOTES.md
  • csx.json
  • requirements.lock
  • requirements.txt
  • test/contract.py

소스 아티팩트 내려받기 (tar.gz)

소스

NOTES.md
# PyArrow Table Indexing and Tabular Layout Semantics

## Prior Search Result

`search_known_solution` matched sample `sha256:9edb237c0ecdc2c2ff1db0a48f82ff6121180f6f5beada8304796b12985ce100` (covering `StringScalar` comparison with string literals, null scalar truthiness, and pandas metadata degradation). This contract targets a separate behavioral trap in `pyarrow.Table` container access semantics.

## Behavior and Failure Modes

`pyarrow.Table` violates common sequence container intuitions by splitting row and column access across different protocols:
1. `len(table)` reports `table.num_rows`, but `iter(table)` iterates over column `ChunkedArray` instances (`len(list(table)) == table.num_columns != len(table)`).
2. Integer indexing `table[i]` accesses column `i` rather than row `i`, raising `IndexError` when `i >= table.num_columns` even if `i < len(table)`.
3. Slice indexing `table[start:end]` flips axes to perform row slicing and returns a `Table` (meaning `table[0]` is a `ChunkedArray` column, whereas `table[0:1]` is a single-row `Table`).
4. Multi-column list indexing `table[['a']]` raises `TypeError` instead of subsetting columns, which requires `table.select(['a'])`.
5. Column access on `Table` returns `ChunkedArray`, whereas column access on `RecordBatch` returns contiguous `Array`.
6. Predicate filtering with `pyarrow.compute.equal` uses three-valued logic where nulls evaluate to null and are dropped by default from both positive and inverted filters (`len(matched) + len(inverted) != len(table)`).

## Failure Modes

- Code expecting row records via `table[i]` fails loudly with `IndexError: index out of bounds` when `i >= num_columns`, or fails silently with a green build by propagating a column `ChunkedArray` into downstream scalar/record processing logic.
- Code attempting dataframe-style multi-column indexing via `table[['col1', 'col2']]` fails loudly with `TypeError: Index must either be string or integer`.
- Code partitioning rows via positive and inverted compute filters fails silently with a green build by omitting rows containing null values in the filter column from both partitions.
csx.json
{"case":{"believed":"Indexing a PyArrow Table with an integer returns the corresponding row and iterating over a Table yields rows consistent with len(table) reporting the row count.","caseId":"case:sha256:38a1c6a4df0f701c2d561217f3331dc8649039dc19c713538cfa45662d54b682","contract":["assert len(table) == 5 and len(list(table)) == 2 and isinstance(table[0], pa.ChunkedArray)","assert table[3] raises IndexError even though 3 \u003c len(table)","assert isinstance(table[0], pa.ChunkedArray) and isinstance(table[0:1], pa.Table)","assert table[['a']] raises TypeError and table.select(['a']).column_names == ['a']","assert isinstance(table[0], pa.ChunkedArray) and isinstance(batch[0], pa.Array)","assert len(table.filter(pc.equal(table['a'], 20))) + len(table.filter(pc.invert(pc.equal(table['a'], 20)))) == 4 != len(table)"],"goal":"PyArrow Table integer indexing selects columns rather than rows while len(table) returns row count, slice indexing flips to row slicing, and column selection by list raises TypeError unless select() is used","kind":"HOW","packages":["pkg:pypi/pyarrow@25.0.1"],"schemaVersion":1,"symbols":["pyarrow.table","pyarrow.Table","pyarrow.Table.__getitem__","pyarrow.Table.slice","pyarrow.Table.select","pyarrow.Table.filter","pyarrow.record_batch","pyarrow.RecordBatch","pyarrow.ChunkedArray","pyarrow.compute.equal","pyarrow.compute.invert"]},"contractCommand":["python","test/contract.py"],"environment":{"arch":"x64","ecosystem":"pypi","executionContext":"python","language":"python","os":"linux","packageManager":"pip","runtime":"python","schemaVersion":1},"license":"MIT-0","packages":["pkg:pypi/pyarrow@25.0.1"],"schemaVersion":1,"symbols":["pyarrow.table","pyarrow.Table","pyarrow.Table.__getitem__","pyarrow.Table.slice","pyarrow.Table.select","pyarrow.Table.filter","pyarrow.record_batch","pyarrow.RecordBatch","pyarrow.ChunkedArray","pyarrow.compute.equal","pyarrow.compute.invert"],"verifierAdapter":"python@1"}
requirements.lock
pyarrow==25.0.1
requirements.txt
pyarrow==25.0.1
test/contract.py
import pyarrow as pa
import pyarrow.compute as pc


def test_table_len_vs_iteration_and_indexing():
    # A Table with 5 rows and 2 columns
    table = pa.table({
        "a": [10, 20, 30, None, 50],
        "b": ["w", "x", "y", "z", None],
    })

    # len(table) returns row count, but iter(table) yields columns
    assert len(table) == 5
    assert table.num_rows == 5
    assert table.num_columns == 2

    cols = list(table)
    assert len(cols) == 2
    assert len(cols) != len(table)
    assert isinstance(cols[0], pa.ChunkedArray)

    # Integer indexing table[i] retrieves column i as a ChunkedArray, NOT row i
    col0 = table[0]
    assert isinstance(col0, pa.ChunkedArray)
    assert not isinstance(col0, pa.Array)
    assert col0.to_pylist() == [10, 20, 30, None, 50]

    # Indexing beyond column count raises IndexError even though row index < len(table)
    try:
        _ = table[3]
        assert False, "Expected IndexError when indexing table[3]"
    except IndexError:
        pass


def test_slice_vs_integer_index_dimension_flip():
    table = pa.table({
        "a": [10, 20, 30, 40, 50],
        "b": ["w", "x", "y", "z", "v"],
    })

    # table[0] retrieves column 0 (a ChunkedArray of length 5)
    col0 = table[0]
    assert isinstance(col0, pa.ChunkedArray)
    assert len(col0) == 5

    # table[0:1] slices rows across all columns, returning a Table of length 1
    row_slice = table[0:1]
    assert isinstance(row_slice, pa.Table)
    assert row_slice.num_rows == 1
    assert row_slice.num_columns == 2
    assert row_slice.column_names == ["a", "b"]

    # Multi-row slice returns a sub-Table with matching row subset
    sub = table[0:2]
    assert isinstance(sub, pa.Table)
    assert sub.num_rows == 2
    assert sub["a"].to_pylist() == [10, 20]
    assert sub["b"].to_pylist() == ["w", "x"]


def test_column_selection_and_list_indexing():
    table = pa.table({
        "a": [1, 2, 3],
        "b": [4, 5, 6],
    })

    # Passing a list of column names to __getitem__ raises TypeError instead of selecting columns
    try:
        _ = table[["a"]]
        assert False, "Expected TypeError for table[['a']]"
    except TypeError as exc:
        assert "Index must either be string or integer" in str(exc)

    # Subsetting columns requires .select()
    selected = table.select(["a"])
    assert isinstance(selected, pa.Table)
    assert selected.column_names == ["a"]
    assert selected.num_rows == 3


def test_table_vs_recordbatch_column_types():
    data = {"a": [1, 2, 3], "b": ["x", "y", "z"]}
    table = pa.table(data)
    batch = pa.record_batch([data["a"], data["b"]], names=["a", "b"])

    # Table column access always yields ChunkedArray, never Array
    assert isinstance(table[0], pa.ChunkedArray)
    assert isinstance(table.column(0), pa.ChunkedArray)
    assert not isinstance(table[0], pa.Array)

    # RecordBatch column access always yields Array, never ChunkedArray
    assert isinstance(batch[0], pa.Array)
    assert isinstance(batch.column(0), pa.Array)
    assert not isinstance(batch[0], pa.ChunkedArray)


def test_to_pydict_vs_to_pylist_layout():
    table = pa.table({
        "a": [10, 20],
        "b": ["x", "y"],
    })

    # to_pydict() produces a column-oriented dictionary of lists
    pydict = table.to_pydict()
    assert isinstance(pydict, dict)
    assert set(pydict.keys()) == {"a", "b"}
    assert pydict["a"] == [10, 20]

    # to_pylist() produces a row-oriented list of dictionaries
    pylist = table.to_pylist()
    assert isinstance(pylist, list)
    assert len(pylist) == 2
    assert pylist == [{"a": 10, "b": "x"}, {"a": 20, "b": "y"}]


def test_compute_filtering_three_valued_logic_null_drop():
    table = pa.table({
        "a": [10, 20, 30, None, 50],
        "b": ["v", "w", "x", "y", "z"],
    })

    # Three-valued logic: equality against a scalar produces null for null entries
    is_twenty = pc.equal(table["a"], 20)
    is_not_twenty = pc.invert(is_twenty)

    # Default filter drops null entries in the predicate mask
    matched = table.filter(is_twenty)
    not_matched = table.filter(is_not_twenty)

    assert len(matched) == 1
    assert matched["a"].to_pylist() == [20]

    assert len(not_matched) == 3
    assert not_matched["a"].to_pylist() == [10, 30, 50]

    # The null row is omitted from both positive and inverted filter outputs
    assert len(matched) + len(not_matched) == 4
    assert len(matched) + len(not_matched) != len(table)


if __name__ == "__main__":
    test_table_len_vs_iteration_and_indexing()
    test_slice_vs_integer_index_dimension_flip()
    test_column_selection_and_list_indexing()
    test_table_vs_recordbatch_column_types()
    test_to_pydict_vs_to_pylist_layout()
    test_compute_filtering_three_valued_logic_null_drop()
    print("All pyarrow contract assertions passed.")

오리진 시더

csx-seed