Decompose io/pyarrow.py into focused modules to enable pluggable compute engines
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 5/5
- Temps estimé
- Plus d'une semaine
- Accessibilité débutants
- 35/100
- Type d'issue
- Refactorisation
- Clarté
- Plutôt claire
- Activité
- Active
- Stack technique
- python
- Domaine
- data-engineering, databases
Piste de recherche
Commencez par pyiceberg/io/pyarrow.py et l’extraction de FileIO décrite dans PR #3738 ; examinez le code existant de PyArrowFile et PyArrowFileIO ainsi que les tests associés. Déplacez uniquement la responsabilité FileIO, préservez les réexportations depuis le chemin de module d’origine et exécutez la suite de tests existante pour vérifier que le comportement et les imports restent inchangés.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Summary
pyiceberg/io/pyarrow.py is a 3,100+ line monolith that handles six unrelated concerns: filesystem I/O, schema conversion, expression translation, scan/read orchestration, write logic, and Parquet statistics. This makes it difficult to test individual components, extend behavior, or substitute alternative engines for specific operations.
This issue proposes an incremental decomposition - a series of small, independently-reviewable refactoring PRs that split the file by concern while maintaining full backward compatibility via re-exports. The end goal is clean seam points where bounded-memory compute engines (DataFusion, etc.) can be introduced for operations that currently OOM on large data.
Motivation
Several open issues depend on bounded-memory compute that PyArrow's kernel library cannot provide:
- Equality delete resolution (#1210, #3270) - requires anti-join with spill
- Sort-on-write (#271) - requires external merge sort
- Data compaction (#1092) - requires sort + join + rewrite pipeline
- CoW deletes on large files - full file materialization causes OOM
A previous attempt to deliver all of this at once (#3715, PR #3716) was rejected for being too large to review. This issue takes the opposite approach: decompose first, add capabilities later.
Approach
Phase 1: Split the monolith (pure refactoring)
Extract each concern into its own module under pyiceberg/io/. The original pyarrow.py becomes a thin re-export shim so all existing imports continue to work.
| PR | Extraction | Approximate scope |
|---|---|---|
| A | FileIO (PyArrowFile, PyArrowFileIO) - #3738 |
~700 lines |
| B | Schema conversion (schema_to_pyarrow, pyarrow_to_schema, visitors) |
~900 lines |
| C | Expression translation (expression_to_pyarrow, _ConvertToArrowExpression) |
~300 lines |
| D | Statistics (StatsAggregator, PyArrowStatisticsCollector, ParquetFormatWriter) |
~500 lines |
| E | Write path (write_file, _dataframe_to_data_files, partitioning, bin packing) |
~1200 lines |
| F | Scan/Read (ArrowScan, _task_to_record_batches, delete resolution) |
~300 lines |
Each PR:
- Moves code, does not change behavior
- Re-exports from the original module path
- All existing tests pass unchanged
- No new dependencies
These PRs are largely independent of each other (no strict ordering required).
Phase 2: Introduce a compute protocol
Once concerns are separated, introduce a thin ComputeEngine protocol for the operations that benefit from bounded-memory execution:
class ComputeEngine(Protocol):
def filter_batches(self, batches, expr, schema) -> Iterator[RecordBatch]: ...
def sort_batches(self, batches, sort_order, schema) -> Iterator[RecordBatch]: ...
def anti_join(self, left, right, keys) -> Iterator[RecordBatch]: ...
The default implementation delegates to the existing PyArrow code. No behavior change, just an indirection point.
Phase 3: DataFusion as optional compute engine
With the protocol in place, a DataFusionComputeEngine implementation slots in as an optional extra. Each capability (equality delete resolution, sort-on-write, etc.) is its own PR wiring the protocol into the specific code path.
What this is NOT
- Not a rewrite. Phase 1 is purely moving existing code into new files.
- Not adding DataFusion as a hard dependency. It remains an optional extra.
- Not changing the public API. All existing imports and behaviors are preserved.
Prior art / references
- #3715 / PR #3716: Previous pluggable backend attempt (rejected as too large)
- Community sync discussion (June 30, 2026): established that read/write/compute should be separable
- #3554: Original DataFusion integration proposal
- #271: Sort-on-write (requires external merge sort)
- #1210, #3270: Equality delete resolution
- #1092: Data compaction
I plan to start with PR A (FileIO extraction, #3738) as a proof of concept for the approach. Feedback on the overall direction is welcome before I proceed further.
- Langage dominant
- Python
- Étoiles
- 1.1k
- Forks
- 589
- Merge moyen
- 1 j 20 h
- PR mergées (30 j)
- 68
Guide de contribution
Aucun guide de contribution indexé pour ce dépôt
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de apache/iceberg-python
-
Difficulté 2/5 1-3 heures Accessibilité débutants 70/100
apache/iceberg-python#4010 · 1 réaction ·
-
kind:bug
Difficulté 1/5 Moins d'une heure Accessibilité débutants 92/100
apache/iceberg-python#4006 ·
-
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
apache/iceberg-python#3996 ·
-
Deletion vector bitmap count is read from the blob and used as a loop bound without validation Ouvertebug
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
apache/iceberg-python#3979 ·
-
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
apache/iceberg-python#3885 ·
Toutes les issues de apache/iceberg-python
Issues similaires
-
bug
Difficulté 2/5 1-3 heures Accessibilité débutants 75/100
stephrobert/dsoxlab#238 ·
-
Difficulté 2/5 1-3 heures Accessibilité débutants 75/100
-
Difficulté 2/5 1-3 heures Accessibilité débutants 75/100
sublimehq/package_control#1780 ·
-
Difficulté 2/5 1-3 heures Accessibilité débutants 65/100
-
Difficulté 2/5 1-3 heures Accessibilité débutants 70/100
nwg-piotr/nwg-displays#145 ·