python-bug-fixes - #1
Merged
Merged
Conversation
Added missing packages to __init__.py and added a test suite to verify this
…s not present, added testing to cover config cases
… the top). This should cascade from the top to the rest of the doc
…tual distribution Identified known bugs and flagged them for fixing further down the line
The build job installed pybind11 via apt (pybind11-dev) but never pip installed it, while CMakeLists.txt probes for it with `python -m pybind11 --cmakedir` under COMMAND_ERROR_IS_FATAL ANY. That probe needs the pip package, so configure aborted. The link job was unaffected because it installs requirements.txt first. CMakeLists.txt: make the probe advisory rather than fatal. Capture the exit code, set pybind11_DIR only on success, and otherwise fall through to find_package so a system pybind11 (e.g. Debian pybind11-dev) still resolves. python-distro.yml: replace the apt pybind11-dev install with `pip install pybind11`, matching pyproject.toml build-system.requires and what the link job already does. Pin the configure step to the interpreter pip installed into with -DPython_EXECUTABLE="$(which python)" so CMake cannot bind to a different Python than the one being built for. Verified both paths locally with CMake 4.4.3: the pip path configures and generates cleanly, and an interpreter without pybind11 now reaches find_package instead of aborting at the probe. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The submodule at python/pybind11 was never wired into the build. The original CMakeLists.txt resolved pybind11 through FetchContent, which downloaded its own copy of v2.12.1 at configure time; there was no add_subdirectory and no reference to the submodule path anywhere in CMakeLists.txt, setup.py, pyproject.toml or build_all.ps1. It has since been replaced by find_package against the pip package, so the submodule is dead weight in every configuration. Removing it reclaims 4.3 MB from the working tree and 15 MB of cached metadata under .git/modules, taking .git from roughly 16 MB to 940 KB. Also drops `submodules: recursive` from both CI checkout steps, since there is nothing left to fetch, and updates the README clone instructions and the release-notes line that described pybind11 as a submodule. Note for existing clones: run `git submodule deinit -f python/pybind11` after pulling if git leaves a stale empty directory behind. Fresh clones are unaffected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…tune(). Otherwise, it will use the default When a user runs auto_tune() it will write to CONFIG_FILE and return an error if it can't
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Gets the project building again, replaces the mocked Python test suite with real
numerical tests, and fixes the packaging metadata needed to publish. In the
process the new tests uncovered 7 genuine defects in the C++ and Python
layers, which are documented as strict-xfail tests rather than silently fixed.
12 commits, 32 files, +3265 / −1313.
Why
main/developcould not be built at all. Three defects stacked:CMakeLists.txtrequiredfind_package(Python 3.14 REQUIRED)v2.12.1, which predates Python 3.13and 3.14 support — so the two requirements were mutually unsatisfiable on any
machine
setup.pypassed-DPYTHON_EXECUTABLE, which modern CMakeFindPythonignores, so CMake could bind to a different interpreter than the wheel was
tagged for
Because nothing built, 11 of 13 Python test files had drifted to mocking the
_fastdistextension entirely — asserting that aMagicMockreturned the valueit was handed. That made an entire class of bug undetectable.
Changes
Build
build_all.ps1already claimed to supportfind_package(pybind11 CONFIG REQUIRED),resolved from the active environment's pip package, with a fallback to a
system install (e.g. Debian
pybind11-dev)setup.pyto passPython_EXECUTABLE(capital P) so CMake binds tosys.executableDevelopment→Development.Module, the correct component for extensionmodules
python/pybind11submodule. It was never wired into thebuild — there was no
add_subdirectoryand no reference to the path anywhere.Reclaims 4.3 MB of working tree and 15 MB under
.git/modulesVersioning
project(fastdist VERSION x.y.z)inCMakeLists.txtis now the single sourceof truth.
version.his generated from a newversion.h.intemplate viaconfigure_file;bindings.cppandsetup.pyboth derive from itdisagreed (0.0.1 vs 0.1.0)
fastdist.__version__andtest_version.py, which fails if the C++constant and the wheel metadata ever drift apart
Packaging
install_requires=["numpy>=1.21"]. Previouslypip installsucceededand
import fastdistthen failed withModuleNotFoundError: numpynvidia-ml-pymoved to an optional[gpu]extrapython_requirescorrected from>=3.7to>=3.12(six modules use PEP 604syntax requiring 3.10+, and CMake requires 3.12)
description,long_descriptionfrom README,url, Apache-2.0 licensemetadata, and classifiers replacing the previous placeholders
Correctness
Bernoulli._mgf_scalar/._cgf_scalarcalled_core.bernoulli_mgf/_core.bernoulli_cgf, which are not bound. Both raisedAttributeErroronany call with valid arguments
ChiSquarewas importable fromfastdist.distributionsbut missing from thetop-level package exports
validate_gpu_capacityraisedNVMLError_Uninitializedout of itsfinallyblock on any machine without an NVIDIA driver. NVML now initializes once per
process with an
atexitteardown, degrades cleanly when unavailable, andaccepts a
device_indexconfig.pyno longer touches the filesystem at import. It previously createda directory and wrote a default config file on
import fastdist, which failsoutright in read-only containers and CI runners. The file is now written only
by an explicit
auto_tune()callCI
develop, not justmaster-DPython_EXECUTABLE="$(which python)"submodules: recursivefrom both checkout steps__pycache__and.pytest_cacheadded to.gitignoreTests
The Python suite was rewritten to exercise the real compiled extension. Every
numeric assertion is made against an independently derived closed form or a
reference implementation, never a value captured from a previous run.
485 tests (mostly mocked) → 1745 tests (1686 passing, 59 documenting known
defects). Zero mocks remain.
New
conftest.pyprovides shared tolerances, aknown_bugmarker, andreference implementations of the regularized lower incomplete gamma and
regularized incomplete beta — validated against hand-computed values before use.
Beyond pointwise checks, each distribution gets structural property tests: PMFs
sum to 1, CDFs are monotonic/bounded/saturating,
K(t) == ln M(t),M(0) == 1,classmethods agree with instance methods, means match independently computed
PMF-weighted sums. Plus identities like exponential memorylessness,
Beta(1,1) ≡ uniform, Gamma(1,θ) ≡ exponential, and
Γ(x+1) = xΓ(x).Array-capable classes additionally cover dtype/shape, numpy input, empty arrays,
2-D and non-numeric rejection, and
step_sizesemantics.Defects found — NOT fixed in this PR
All are marked
@pytest.mark.xfail(strict=True)withknown_bug. The suitestays green, and each becomes a hard failure the moment it's fixed and its
marker goes stale, so none can be fixed and forgotten.
Beta(1,1).cdf(0.5)→ 0.6534 (exact: 0.5);Beta(0.5,0.5).cdf(0.5)→ −0.596, a negative probabilityGamma.cdfandChiSquare.cdf; errors to 0.26 absolute;ChiSquare(3).cdf(7.5)→ 1.000498, a probability > 1Beta.betasetterTypeErrorfor every value —if alpha <= 0sits outside itsis not NoneguardBinomial.psetterTypeErrorfor every valueDiscreteUniform.bsetterself.b = valueinstead ofself._b→RecursionErrorinfat k=170,nanfrom k=200.C(k+r−1,k)via raw factorials; the coefficient itself is only 20301Uniformsetters skip cross-bound validationa=10, b=−10, after which every method silently returnsnan#2 is the most serious for users — chi-square CDFs feed hypothesis tests, and
returning >1 corrupts them silently.
Run
pytest -m known_bug -vto see them.Notes for reviewers
git submodule deinit -f python/pybind11after pullingnetwork access at configure time.
pip install .handles this viabuild-system.requires; a directcmakeinvocation needspip install pybind11firstpython_requiresnarrowed to>=3.12. 3.7–3.11 never actually workedFollow-ups (not in scope here)
Fix the 7 defects above;
MANIFEST.in(the sdist currently ships no C++ sourcesand is unbuildable);
py.typedand.pyistubs; the PyPI namefastdistisalready taken; wire the C++ tests into
ctest(they're built but never run, andtheir
assert()s are stripped underNDEBUG); CI matrix across 3.12–3.14 andLinux/macOS/Windows.