From 9c7fbf41db4a4b3698ce6784eaf61d6eb988dbea Mon Sep 17 00:00:00 2001 From: vahid-ahmadi Date: Wed, 16 Sep 2026 13:06:12 +0100 Subject: [PATCH 1/2] Declare subpackages instead of shipping the source tree as package data 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 --- changelog.d/211.fixed.md | 1 + microimpute/py.typed | 0 pyproject.toml | 19 +++++++++++++++---- 3 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 changelog.d/211.fixed.md create mode 100644 microimpute/py.typed diff --git a/changelog.d/211.fixed.md b/changelog.d/211.fixed.md new file mode 100644 index 00000000..c08e656c --- /dev/null +++ b/changelog.d/211.fixed.md @@ -0,0 +1 @@ +The wheel now declares its subpackages properly instead of sweeping the source tree in as package data, so stale `__pycache__` and other working-tree files no longer ship. Adds `py.typed`, the full author list, classifiers and project URLs. diff --git a/microimpute/py.typed b/microimpute/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/pyproject.toml b/pyproject.toml index f1134e01..9b46a166 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,9 +11,16 @@ version = "3.1.1" description = "Benchmarking imputation methods for microdata" readme = "README.md" authors = [ + { name = "Vahid Ahmadi" }, + { name = "Max Ghenis", email = "max@policyengine.org" }, { name = "MarĂ­a Juaristi", email = "juaristi@uni.minerva.edu" }, { name = "Nikhil Woodruff", email = "nikhil.woodruff@outlook.com" } ] +classifiers = [ + "Intended Audience :: Science/Research", + "Programming Language :: Python :: 3", + "Topic :: Scientific/Engineering :: Information Analysis", +] requires-python = ">=3.12,<3.15" dependencies = [ "numpy>=2.0.0,<3.0.0", @@ -62,12 +69,16 @@ images = [ "kaleido>=0.2.1,<0.3.0", # For exporting plots as PNG/JPG ] -[tool.setuptools] -packages = ["microimpute"] -include-package-data = true +[project.urls] +Repository = "https://github.com/PolicyEngine/microimpute" +Documentation = "https://policyengine.github.io/microimpute" +Issues = "https://github.com/PolicyEngine/microimpute/issues" + +[tool.setuptools.packages.find] +include = ["microimpute*"] [tool.setuptools.package-data] -"microimpute" = ["**/*"] +"microimpute" = ["py.typed"] [tool.towncrier] package = "microimpute" From f34a3f03a54ba7d3d94ac3d7869748ed890f04c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mar=C3=ADa=20Juaristi?= <127882282+juaristi22@users.noreply.github.com> Date: Thu, 17 Sep 2026 11:27:26 +0100 Subject: [PATCH 2/2] Fix issues from review: format documentation examples --- docs/imputation-benchmarking/cross-validation.md | 12 ++++++------ docs/imputation-benchmarking/preprocessing.md | 8 ++++---- docs/imputation-benchmarking/visualizations.md | 8 ++------ docs/models/imputer/implement-new-model.md | 4 +--- docs/use_cases/index.md | 12 ++++++------ 5 files changed, 19 insertions(+), 25 deletions(-) diff --git a/docs/imputation-benchmarking/cross-validation.md b/docs/imputation-benchmarking/cross-validation.md index 8da745ff..c1b6f93e 100644 --- a/docs/imputation-benchmarking/cross-validation.md +++ b/docs/imputation-benchmarking/cross-validation.md @@ -41,23 +41,23 @@ Returns a dictionary containing separate results for each metric type: ```python { "quantile_loss": { - "results": pd.DataFrame, # rows: ["train", "test"], cols: quantiles (mean across folds) + "results": pd.DataFrame, # rows: ["train", "test"], cols: quantiles (mean across folds) "results_std": pd.DataFrame, # rows: ["train", "test"], cols: quantiles (std across folds) "mean_train": float, "mean_test": float, "std_train": float, "std_test": float, - "variables": List[str] # numerical variables evaluated + "variables": List[str], # numerical variables evaluated }, "log_loss": { - "results": pd.DataFrame, # rows: ["train", "test"], cols: quantiles + "results": pd.DataFrame, # rows: ["train", "test"], cols: quantiles "results_std": pd.DataFrame, # rows: ["train", "test"], cols: quantiles (std across folds) "mean_train": float, "mean_test": float, "std_train": float, "std_test": float, - "variables": List[str] # categorical variables evaluated - } + "variables": List[str], # categorical variables evaluated + }, } ``` @@ -77,7 +77,7 @@ results = cross_validate_model( data=diabetes_df, predictors=["age", "sex", "bmi", "bp"], imputed_variables=["s1", "s4"], - n_splits=5 + n_splits=5, ) # Check performance for numerical variables diff --git a/docs/imputation-benchmarking/preprocessing.md b/docs/imputation-benchmarking/preprocessing.md index 736d73ed..05693943 100644 --- a/docs/imputation-benchmarking/preprocessing.md +++ b/docs/imputation-benchmarking/preprocessing.md @@ -117,10 +117,10 @@ result = autoimpute( predictors=["age", "education"], imputed_variables=["income", "wealth"], preprocessing={ - "income": "log", # Log transform (positive values only) - "wealth": "asinh", # Asinh transform (handles zeros/negatives) - "age": "normalize" # Z-score normalization - } + "income": "log", # Log transform (positive values only) + "wealth": "asinh", # Asinh transform (handles zeros/negatives) + "age": "normalize", # Z-score normalization + }, ) ``` diff --git a/docs/imputation-benchmarking/visualizations.md b/docs/imputation-benchmarking/visualizations.md index 21dde021..fe8f87b8 100644 --- a/docs/imputation-benchmarking/visualizations.md +++ b/docs/imputation-benchmarking/visualizations.md @@ -83,11 +83,7 @@ comparison_viz = method_comparison_results( ) # Generate plot -fig = comparison_viz.plot( - title="Method comparison", - show_mean=True, - plot_type="bar" -) +fig = comparison_viz.plot(title="Method comparison", show_mean=True, plot_type="bar") fig.show() # Get summary statistics @@ -165,7 +161,7 @@ perf_viz = model_performance_results( results=cv_results, model_name="QRF", method_name="Cross-validation", - metric="quantile_loss" + metric="quantile_loss", ) fig = perf_viz.plot(title="QRF performance") diff --git a/docs/models/imputer/implement-new-model.md b/docs/models/imputer/implement-new-model.md index edf21254..794d6193 100644 --- a/docs/models/imputer/implement-new-model.md +++ b/docs/models/imputer/implement-new-model.md @@ -73,9 +73,7 @@ class NewModelResults(ImputerResults): except Exception as e: self.logger.error(f"Error during Model prediction: {str(e)}") - raise RuntimeError( - f"Failed to predict with Model: {str(e)}" - ) from e + raise RuntimeError(f"Failed to predict with Model: {str(e)}") from e ``` ## Implementing the main model class diff --git a/docs/use_cases/index.md b/docs/use_cases/index.md index 32c7af96..2c9ff07c 100644 --- a/docs/use_cases/index.md +++ b/docs/use_cases/index.md @@ -23,7 +23,7 @@ Before imputation, make sure both datasets have compatible variables. Identify c ```python # Identify common variables -common_variables = ['age', 'income', 'education', 'marital_status', 'region'] +common_variables = ["age", "income", "education", "marital_status", "region"] # Ensure variable formats match (example: education coding) education_mapping = { @@ -31,19 +31,19 @@ education_mapping = { 2: "high_school", 3: "some_college", 4: "bachelor", - 5: "graduate" + 5: "graduate", } # Apply standardization to both datasets for dataset in [scf_data, cps_data]: - dataset['education'] = dataset['education'].map(education_mapping) + dataset["education"] = dataset["education"].map(education_mapping) # Convert income to same units (thousands) - if 'income' in dataset.columns: - dataset['income'] = dataset['income'] / 1000 + if "income" in dataset.columns: + dataset["income"] = dataset["income"] / 1000 # Identify target variable in donor dataset -target_variable = ['networth'] +target_variable = ["networth"] ``` ## Performing imputation