Skip to content

Declare subpackages instead of shipping the source tree as package data - #216

Merged
vahid-ahmadi merged 3 commits into
mainfrom
fix/211-packaging
Sep 21, 2026
Merged

vahid-ahmadi merged 3 commits into
mainfrom
fix/211-packaging

Conversation

@vahid-ahmadi

@vahid-ahmadi vahid-ahmadi commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #211.

Setuptools now discovers microimpute and its subpackages explicitly and excludes tests, documentation, examples, and experiments from package discovery. Replacing the recursive package-data glob with an explicit py.typed entry prevents bytecode and stray working files from entering distributions. Package metadata lists the four authors, Python 3.12–3.14 classifiers, and repository, documentation, and issue links.

The packaging change addresses contamination from a dirty build tree. It does not establish that published wheels were contaminated. License work remains separate in #197.

Package-layout validation built a source distribution and then a wheel from it. Both retained all 27 expected Python modules and py.typed, and excluded injected bytecode and stray CSV/JSON files. Six imports resolved to the extracted wheel outside the checkout; an independent OLS numerical check and two artifact smoke tests passed. These checks preceded the base rebase; verification confirmed unchanged package-discovery/data settings and source contents, with only upstream version and lint metadata updates.

The branch includes #218's shared lint repair; Ruff 0.16.7 formatting and git diff --check pass.

Checks for current head 6a0e9b7.

@vercel

vercel Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
microimpute-dashboard Ready Ready Preview Sep 21, 2026 10:58am UTC

@vahid-ahmadi

Copy link
Copy Markdown
Contributor Author

Reviewed with a fresh pass, including building wheels from clean and deliberately-dirty trees rather than taking the numbers on trust.

The core claim is confirmed, and the mechanism is worse than the description says in one respect and better in another. Neutering only the data glob on the base tree collapses the wheel to 6 files, 9,408 bytes — proving all 25 subpackage modules were shipping as package data rather than declared code. And the fix works: with __pycache__ plus a planted stray CSV and JSON, the built wheel is 127,755 bytes, 32 files, and unzip -l | grep -Ec 'pycache|\.pyc|stray' returns 0.

But the bloat is latent, not shipped. The published 3.1.1 wheel on PyPI is 127,432 bytes — clean. versioning.yaml:60-63 runs make install then python -m build on a fresh checkout without importing or testing, so no bytecode exists at build time. One make test before make build, or any local build, turns it into real 3–5× bloat plus leaked working files.

I could not reproduce the 501 KB figure: I measured 361 KB with one interpreter's __pycache__ and 574 KB with two.

To do

Before merging

  • Correct the overstated framing in the PR body and in changelog.d/211.fixed.md. Say the bloat is latent — CI's clean checkout has so far avoided it — and either drop the 501 KB figure or qualify it as one particular dirty tree. As written it implies shipped wheels are affected, and PyPI shows they are not.
  • Say something about the licence. This PR adds authors, classifiers and URLs — the natural moment — but leaves no license key, no license-files, no License :: classifier, and there is no LICENSE file in the repo, so PyPI shows "License: None". Deferring to microimpute has no licence, so all rights are reserved #197/Add MIT license #220 is defensible; just state it in the body so it reads as a decision. Note Add MIT license #220 will need to add its licence classifier to the list this PR introduces, so merging this first is the right order.

Optional

  • Add Programming Language :: Python :: 3.12 / 3.13 / 3.14 — requires-python is >=3.12,<3.15 but no per-version classifiers ship. All three current classifiers validate against trove_classifiers, and twine check passes on both wheel and sdist.
  • Give Vahid an email in authors. Without one, setuptools splits him into the legacy Author: field while the other three land in Author-email: — correct per spec, but it reads oddly on PyPI.
  • exclude = ["tests*", "docs*", "examples*", "experiments*"] alongside the include. microimputation-dashboard/ matches the glob textually but setuptools skips it (hyphen, no __init__.py) — confirmed absent from the wheel — so this is belt and braces.
  • Follow-up: MANIFEST.in with include CHANGELOG.md LICENSE and prune tests. tests/ currently ships in the sdist and CHANGELOG.md does not; both are pre-existing.
  • Split out the five docs/** formatter reflows — byte-identical hunks appear in Give each per-variable QRF model its own seed #214 and Fix pre-submission imputation and evaluation correctness #219.

Verified, no action needed

  • Nothing is dropped by removing **/*. git ls-files microimpute | grep -v '\.py$' returns only py.typed. The only open() calls (mdn.py:631,643) use a caller-supplied path, and there is no pkgutil / importlib.resources / pkg_resources usage.
  • Every module still imports from the installed wheel — 27 imported from a fresh venv outside the repo; the 3 failures are matching, statmatch_hotdeck and mdn, all missing optional extras, and all three files are present in the wheel listing.
  • py.typed is in the built wheel, not just the source tree.
  • Fix pre-submission imputation and evaluation correctness #219 does not touch packaging at all, so this is not redundant to it.

vahid-ahmadi added a commit that referenced this pull request Sep 21, 2026
The previous approach reformatted five documentation files and bounded
ruff to <0.17.0. Per review, the bound was a no-op against the failure
it targeted: 0.16.0 through 0.16.8 all format markdown and all satisfy
it, so only the reformatting was doing any work - and the next formatter
change inside 0.16.x would reopen the failure.

Excludes docs/**/*.md via [tool.ruff] instead, which fixes the cause
rather than the symptom, and drops the five reformatted files. That also
removes the byte-identical docs hunks that collided with #216, #217 and
#219.

The dev extra is bounded to match CI, so a contributor running
make format no longer reformats files CI then rejects.

The cause was ruff 0.16.0, not 0.16.7: 0.13, 0.14 and 0.15 report '65
files already formatted' and do not scan markdown at all.
@juaristi22

Copy link
Copy Markdown
Collaborator

Review of 019aaaa: No implementation defect found in this PR. The remaining merge blocker is the inherited Lint failure.

Merge blocker — incorporate #218 and rerun CI. The Lint job fails because Ruff would reformat five unchanged Markdown files: docs/imputation-benchmarking/cross-validation.md, preprocessing.md, visualizations.md, docs/models/imputer/implement-new-model.md, and docs/use_cases/index.md. The workflow runs make check-format. #218 fixes the shared failure by excluding Markdown and aligning the development and CI Ruff ranges at >=0.16.0,<0.17.0. Merge #218 first, update this branch, and require green checks on the resulting head.

Validation at the reviewed head: built an sdist and then a wheel from that sdist. Both retained all 27 expected Python modules and py.typed; neither included injected bytecode or stray CSV/JSON files. The wheel excluded tests/docs/examples/experiments packages. Six imports resolved to the extracted wheel outside the checkout, an independent OLS numerical check passed, and both artifact smoke tests passed. Unit/smoke and changelog CI passed; Lint failed. The packaging fix prevents contamination from a dirty build tree; the review does not claim published wheels were already contaminated. License work remains tracked separately in #197.

Integration: read-only merge checks found no textual conflicts in the cumulative #218 + #214 + #215 + #216 + #217 tree. This is not a combined-suite result. #219 conflicts with #214, #215, #217, and #218, so its later rebase must retain the seed, Matching, API, and formatter fixes. The PR description cites an older final commit and historical green checks; update it to the resulting implementation and current validation.

vahid-ahmadi and others added 3 commits September 21, 2026 11:57
packages = ["microimpute"] with package-data "**/*" meant the
subpackages reached the wheel only as package data, swept in by a glob
that also collected whatever else was in the working tree. A wheel built
from a tree with compiled bytecode present carried 27 __pycache__
entries and around 500 KB of build-host bytecode, so wheel contents were
a function of the builder's working directory rather than the source.

setuptools.packages.find declares them properly. Verified: with 54 .pyc
files present in the tree, the built wheel now contains none, and every
subpackage imports from the installed wheel.

Also adds py.typed, so the annotations become visible to downstream
consumers; the two missing authors, which left the paper's corresponding
author out of the PyPI metadata; and classifiers and project URLs, with
no repository link previously on the PyPI page.

The absent LICENSE file is #197 and is not addressed here.

Fixes #211
Per review. Adds Python 3.12/3.13/3.14 classifiers to match
requires-python, an email for Vahid so all four authors render in
Author-email rather than one splitting into the legacy Author field, and
an explicit exclude alongside the include as belt and braces.

Rewords the changelog fragment: the bloat is latent rather than shipped.
CI builds from a fresh checkout with no imports, so published wheels
have been clean - the problem appears when anyone builds from a tree
that has been tested in. The previous wording implied released wheels
were affected.

Also drops the docs reformatting, which belongs to #218.
@juaristi22

Copy link
Copy Markdown
Collaborator

Critical fixed

Updated the branch onto current main, incorporating #218's shared lint repair and the 3.1.2 release. The final diff retains this PR's package-discovery settings, explicit py.typed package data, metadata, and changelog fragment.

Should-address fixed

Refreshed the description to state the dirty-build contamination risk and current validation evidence. License work remains separate in #197.

Verification

  • Source and base-integration verification passed. Package-discovery/data settings and source contents are unchanged; the rebase incorporated upstream version and lint metadata.
  • Earlier package-layout validation built the source distribution and its wheel, retained all 27 Python modules plus py.typed, and excluded injected bytecode and CSV/JSON files. Six artifact imports, the independent OLS check, and two artifact smoke tests passed. These are pre-rebase artifact results, not a rebuild of version 3.1.2.
  • Ruff 0.16.7 formatting and git diff --check passed; make format changed no files.

Pushed head: 6a0e9b7; current-head checks.

GitHub CI: All seven current-head checks passed, including lint, changelog, Python 3.12 smoke tests, Python 3.14 tests with R, and Vercel preview. GitHub reports this pull request as mergeable. (run).

juaristi22 added a commit that referenced this pull request Sep 21, 2026
@vahid-ahmadi
vahid-ahmadi merged commit a60106f into main Sep 21, 2026
7 checks passed
@vahid-ahmadi
vahid-ahmadi deleted the fix/211-packaging branch September 21, 2026 12:22
@vahid-ahmadi vahid-ahmadi mentioned this pull request Sep 21, 2026
38 tasks

This branch was successfully deployed

1 active deployment
Preview — 6a0e9b79 Deployed Sep 21, 2026 by vercel[bot]
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.

Wheel ships subpackages as package data, sweeping in stale __pycache__ and working-tree junk

2 participants