Skip to content

fix: declare pyarrow, pin worker interpreter, add CI + cleanup#1

Open
hamed wants to merge 7 commits into
mainfrom
fix/arrow-dep-and-ci
Open

fix: declare pyarrow, pin worker interpreter, add CI + cleanup#1
hamed wants to merge 7 commits into
mainfrom
fix/arrow-dep-and-ci

Conversation

@hamed

@hamed hamed commented Jul 25, 2026

Copy link
Copy Markdown
Owner

The test suite had never been run. Doing so surfaced two defects that would
hit any user or contributor installing from a clean environment.

pyarrow was an undeclared runtime dependency

bootstrap.sample() calls applyInPandas, which requires Arrow
serialization. pyarrow appears nowhere in pyproject.toml, so a clean
pip install replicas produced a package whose core function raised:

PySparkImportError: [PACKAGE_NOT_INSTALLED] PyArrow >= 18.0.0 must be
installed; however, it was not found.

Declared as pyarrow>=4.

Spark workers ran the wrong interpreter

With pyarrow present the driver was fine, but every worker died:

File ".../pyspark/worker.py", line 2930, in read_udfs
    import pyarrow as pa
ModuleNotFoundError: No module named 'pyarrow'

Spark spawns workers as separate processes and picks the interpreter from
PYSPARK_PYTHON, falling back to python3 on PATH — not the virtualenv
running pytest. All 7 bootstrap tests failed. tests/conftest.py now pins
PYSPARK_PYTHON and PYSPARK_DRIVER_PYTHON to sys.executable.

pandas was uncapped

PySpark warns "does not yet fully support pandas >= 3.0.0". Uncapped, the
newest interpreter resolved to the least-supported pandas: 3.13 pulled pandas
3.0.5 and emitted 14 warnings per run, 3.9 resolved to 2.3.3 and emitted none.
Capped to <3; the suite is now warning-free.

One SparkSession fixture, not two

Both test modules defined a session-scoped spark fixture calling
getOrCreate(). That is not two sessions but one session with two teardowns —
whichever module finished first called .stop() while the other might still
need it. It passed on collection ordering alone. Now a single fixture in
conftest.py.

CI

The dependency bugs share a shape: they only appear where nothing is
preinstalled. .github/workflows/test.yml installs from pyproject.toml
alone into a fresh uv venv on Python 3.9-3.13, then runs pytest. 3.9 resolves
to pyspark 4.0.4 and 3.10+ to 4.2.x, so both resolution paths are covered. A
ruff lint/format gate runs alongside, pinned to the dev extra's version.

Housekeeping

ruff check --fix and ruff format across the package; Homepage/Issues
corrected from allaei/replicas to hamed/replicas.

README.md and examples/*.ipynb are excluded from the formatter only.
Ruff rewrites Python inside README code blocks, discarding alignment chosen
for readability, and reformatting every notebook cell produced a 420-line diff
on a file that still has to be executed. Both remain linted.

Verification

12 passed, zero warnings, on Python 3.13 (pyspark 4.2.0) and on a
from-scratch Python 3.9 env (pyspark 4.0.4). The CI lint and test commands
were each run locally as written. The 5-leg matrix went green on GitHub
runners before the cleanup commits were added.

Still open, not in this PR

  • examples/precision_recall.ipynb has 27 code cells and no outputs, so the
    bootstrap-band plot the README is built around does not render on GitHub.
  • docs/ is empty.
  • README says pip install replicas; the package is not on PyPI.

🤖 Generated with Claude Code

hamed and others added 7 commits July 26, 2026 00:38
bootstrap.sample() calls applyInPandas, which requires Arrow serialization,
but pyarrow was never declared. A clean install produced a package whose
core function raised at runtime:

    PySparkImportError: [PACKAGE_NOT_INSTALLED] PyArrow >= 18.0.0 must be
    installed; however, it was not found.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Spark spawns Python workers as separate processes, choosing the interpreter
from PYSPARK_PYTHON and falling back to `python3` on PATH. That is not the
virtualenv interpreter running pytest, so the driver imported pyarrow while
every worker died with ModuleNotFoundError, failing all 7 bootstrap tests.

Pin PYSPARK_PYTHON and PYSPARK_DRIVER_PYTHON to sys.executable in conftest so
the suite runs with no shell setup.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nothing verified that the declared dependencies were sufficient to install and
run the library. Both bugs fixed in the preceding commits were of that shape:
they only appeared in an environment where nothing was preinstalled.

Install from pyproject alone in a fresh uv venv on every supported
interpreter, then run pytest. 3.9 resolves to pyspark 4.0.4 and 3.10+ to
4.2.x, so both resolution paths are covered.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
PySpark warns "does not yet fully support pandas >= 3.0.0" and recommends
staying below it. With pandas uncapped the newest interpreter resolved to the
least-supported pandas: Python 3.13 pulled pandas 3.0.5 and emitted 14
warnings per test run, while 3.9 resolved to 2.3.3 and emitted none. Capping
to <3 drops the suite to zero warnings.

Homepage and Issues pointed at github.com/allaei/replicas; the repository is
github.com/hamed/replicas.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
test_bootstrap.py and test_metrics.py each defined a session-scoped `spark`
fixture calling getOrCreate(). Since getOrCreate returns the same JVM session
to every caller, this was not two sessions but one session with two teardowns:
whichever module finished first called .stop() while the other might still
need it. It passed on collection ordering alone.

One fixture in conftest.py, so the session lifetime is unambiguous.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ruff check --fix (import sorting, collections.abc.Sequence over the deprecated
typing alias, duplicate notebook imports) and ruff format across the package.

README.md and examples/*.ipynb are excluded from the formatter. Ruff rewrites
Python inside README code blocks, discarding alignment chosen for readability,
and reformatting every notebook cell produced a 420-line diff on a file that
still has to be executed. Both remain linted; only reformatting is off, and
E402 is ignored for notebooks, where imports sit next to the cell that needs
them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Held back until the existing 11 violations were fixed, so the gate lands green
rather than red. Ruff is pinned to the same version as the dev extra: an
unpinned linter fails CI on a diff that cannot be reproduced locally.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@hamed hamed changed the title fix: declare pyarrow, pin worker interpreter, add CI fix: declare pyarrow, pin worker interpreter, add CI + cleanup Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant