跳转至

v0.6.2

Patch release fixing a silent WOE-plot failure on the equal_freq engine and hardening _plot_woe against future silent regressions.

The bug

FeatureValidationPipeline(woe_engine="equal_freq", plot_outputs=True) produced zero PNGs under figs/woe/ on every 0.5.x / 0.6.0 / 0.6.1 release, with no log line, no warning, and no error. Users saw an empty output directory and had no signal that anything had failed.

Two independent defects combined to make the failure invisible:

  1. WOE_Master.plot_bivar_graph(self, data, group, dirname, varlist=None) declared group as a required positional argument. FeatureValidationPipeline._plot_woe called it as engine.plot_bivar_graph(transformed, dirname=str(base_dir)) for the ungrouped case — no group — which raised TypeError: missing 1 required positional argument: 'group'.
  2. The entire _plot_woe body was wrapped in a bare except Exception: return. Every exception — including the TypeError above — was silently swallowed with no log, no warning, no re-raise.

The monotone engine takes a different branch (engine.plot_woe_graph) so the blind spot only affected equal_freq (and any other engine exposing plot_bivar_graph as its plotting entry point).

The fix

  • WOE_Master.plot_bivar_graph API surface: group now defaults to None. The underlying get_bivar_graph(..., group=None, ...) primitive has always accepted an ungrouped call — only the WOE_Master wrapper enforced a required kwarg. Positional order is preserved (data, group, dirname, varlist) so any pre-0.6.2 positional caller still works. dirname is now validated explicitly at call time with a clear TypeError if omitted.
  • Ownership of mkdir: plot_bivar_graph now runs os.makedirs(save_dir, exist_ok=True) before calling get_bivar_graph. Previously callers were expected to pre-create every subdirectory; this matched neither feature_validation (which only created the base directory) nor most external users.
  • FeatureValidationPipeline._plot_woe call site: now passes group=None explicitly for documentation and future-proofing.
  • _plot_woe never silently swallows again: the outer except Exception: return now emits a logger.warning that names the engine, the target, the output directory, and the underlying exception (error=%r). The function still returns rather than raising — plot failure should not kill an entire feature-validation run — but the failure is now visible.

Compatibility

  • Purely additive on the WOE_Master.plot_bivar_graph signature. Any caller that was passing group= and dirname= as keywords (both internal call sites do) is unaffected. Any caller passing all four positionally is unaffected. The one edge case is a caller that omitted the previously-required group argument — such a caller would have been crashing all along, so 0.6.2 is strictly a fix.
  • No changes to plot_woe_graph (monotone engine) or its call site.
  • No configuration surface changes: plot_outputs, woe_engine, woe_plot_groups all behave identically to 0.6.1 — with the difference that equal_freq now actually produces the promised PNGs.

Test-environment baseline

The pytest suite now also requires statsmodels>=0.14 (VIF path in Feature_Screen NaN-handling regression) and PyYAML>=6.0 (optional config_to_yaml/config_from_yaml round-trip). Both are declared in SuperModelingFactory_pytest/requirements-dev.txt and installed by tests.yml. The full suite is now 662 passed / 0 skipped / 0 failed on the modern matrix.

Durable lesson

Bare except Exception: return in a library is a bug in itself, even before it hides a specific defect. Every silenced exception is a monitoring failure waiting to be discovered by a user. The correct pattern in SMF from 0.6.2 forward is except Exception as exc: _logger.warning(..., error=%r, exc); return — log first, decide the recovery second.