Skip to content

fix(enterprise): detect_label_issues no longer hangs from unguarded scripts; FPE tests pass with pyffx - #433

Merged
kevincostner17 merged 1 commit into
mainfrom
fix/optional-extras-cleanlab-pyffx
Sep 16, 2026
Merged

kevincostner17 merged 1 commit into
mainfrom
fix/optional-extras-cleanlab-pyffx

Conversation

@kevincostner17

Copy link
Copy Markdown
Contributor

Summary

This PR fixes two problems that only appear when optional extras are installed. Both were found by the extras install campaign (FDC-L2-003, FDC-L2-004).

  • detect_label_issues could hang forever. With the [cleanlab] extra on macOS, calling it from a plain script that has no if __name__ == "__main__" guard never returned.
  • The privacy suite failed with the [privacy] or [all] extra. test_fpe_falls_back_to_surrogate_without_crypto failed whenever those extras were installed, so CI with them was red.

Root cause

  • Label issues: the wrapper left cleanlab's find_label_issues at its default n_jobs=None, which starts one worker per core.
    • macOS and Windows start workers with spawn, and each worker re-imports __main__.
    • In an unguarded script, every worker re-entered detect_label_issues. Multiprocessing then raised its freeze_support RuntimeError in a loop and the call never returned.
    • The existing test only covered the "cleanlab missing" path, so CI never ran the real call.
  • FPE test: the test asserted the surrogate fallback but never hid pyffx. With pyffx installed (it ships in [privacy] and [all]), fpe_mode is crypto_fpe.

Behaviour change

  • Default: detect_label_issues now passes n_jobs=1 unless the caller sets n_jobs.
  • Explicit n_jobs: passed through unchanged.
  • Docs: the docstring explains the default.
  • detect_outliers: unchanged. cleanlab's OutOfDistribution does not use multiprocessing.

Default-output changes

None. Results are identical. detect_label_issues runs in one process unless n_jobs is given, which can be slower on very large inputs.

Tests

  • tests/test_enterprise_cleaner.py:
    • With a stub cleanlab module, the wrapper passes n_jobs=1 by default and keeps an explicit n_jobs=4.
    • When cleanlab is installed, a real unguarded script calling detect_label_issues exits 0 and prints [2], with a 120 s timeout.
  • tests/test_enterprise_privacy.py:
    • The surrogate test hides pyffx with monkeypatch.setitem(sys.modules, "pyffx", None) and asserts the exact surrogate mode string. The old startswith check was loose, and surrogate_format_preserving_not_crypto_fpe contains crypto_fpe as a substring.
    • New test_fpe_uses_crypto_when_pyffx_is_installed asserts crypto_fpe with the length and all-digit format preserved. It is skipped when pyffx is absent.

Verification

  • ruff check and mypy on the changed files: clean.
  • tests/test_enterprise_cleaner.py and tests/test_enterprise_privacy.py passed in:
    • the dev venvs, py3.12 / pandas 2.3.3 and py3.9 / pandas 1.5.3 (no cleanlab, no pyffx; the extras-only tests skip)
    • an [cleanlab] py3.12 venv (cleanlab 2.9.0), where the real unguarded-script test runs
    • [privacy] venvs on py3.12 and py3.9 (pyffx installed), where both FPE tests run
  • The campaign repro FDC-L2-003-cleanlab-module-level-hang.py against this branch: the unguarded script exits 0 after about 2 s. On main it was still running after 60 s and had to be killed.

…est FPE with and without pyffx

detect_label_issues passed cleanlab's default n_jobs, which starts one worker per core. On spawn platforms (macOS, Windows) a call from a plain script without a __main__ guard re-imported the script in every worker and never returned. Default n_jobs to 1; an explicit n_jobs is passed through.

test_fpe_falls_back_to_surrogate_without_crypto asserted the surrogate mode without hiding pyffx, so it failed whenever the [privacy] or [all] extra was installed. Hide pyffx in that test and add a test for the crypto_fpe path when pyffx is present.
@coderabbitai

coderabbitai Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 31ae753a-3155-4968-8685-573623a7ecb0


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

FreshData benchmark report — performance

  • freshdata: ?
  • python: ?
  • platform: ?
fixture n_rows n_cols p50 s p95 s peak MB repair % false-repair % preserve % trust monotonic export %

Authored-code reduction (Metric 6)

@kevincostner17
kevincostner17 merged commit f32bedc into main Sep 16, 2026
22 checks passed
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