Skip to content

Preserve fields when sampling one dictionary - #717

Merged
juarezr merged 2 commits into
petl-developers:masterfrom
umd0730:fix/single-record-header-sample
Sep 21, 2026
Merged

juarezr merged 2 commits into
petl-developers:masterfrom
umd0730:fix/single-record-header-sample

Conversation

@umd0730

@umd0730 umd0730 commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

fromdicts([{'id': '001'}], sample=1) currently yields [(), ()]: both the discovered header and all field values disappear. Passing the same data as a generator gives a different result. Empty inputs with sample=1 also raise RuntimeError, and the same problems affect JSON array input.

iterpeek(..., 1) returns a single object rather than a list. Header discovery then iterates the dictionary's keys as though they were sampled records. Collect the sample with islice and replay it with chain, in both ordinary and cached-generator header discovery. Sample sizes 0 and greater than 1 retain their existing behavior; records used for discovery remain available as data rows.

Validation

Windows / Python 3.12.14, based on master 9a0b8448228b2575713dce93dacfc8451a4152b9:

  • Before the fix: 7 failed, 33 passed in the JSON test module, reproducing missing columns/values and empty-input exceptions.
  • After: python -m pytest petl -q --tb=short --disable-warnings: 606 passed, 16 skipped, with five database-related warnings. Optional external integrations and the full tox matrix were not exercised locally.
  • Fourteen added cases cover lists, one-pass iterators, cached generators, sample sizes 0/1/2, empty inputs, repeated iteration and JSON array files.

This is separate from #716: that PR fixes empty JSON Lines; this fixes sampled dictionary/JSON-array header discovery and does not include the #716 commits.

Checklist

  • Regression tests, behavior documentation and changelog included.
  • Atomic, reversible fix with no unrelated source changes.
  • Tested locally against current master.
  • Upstream CI passed all 27 jobs at d199558; the separate CodeQL workflow also succeeded.
  • Coveralls reports 37/37 patch lines covered (100%), no coverage regressions, and overall coverage 92.09% for CI build 35120679796.
  • Ready to review.

No new public function is introduced.

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Preserve fields when sampling one dictionary

🐞 Bug fix 🧪 Tests 📝 Documentation 🕐 10-20 Minutes

Grey Divider

AI Description

• Preserve headers and values when dictionary or JSON-array sampling uses sample=1.
• Return empty tables safely for empty sampled inputs.
• Maintain existing sampling behavior across lists, iterators, generators, and repeated iteration.
Diagram

graph TD
  A["Input APIs"] --> B["Dictionary view"] --> C["Bounded sample"] --> D["Discover header"]
  C -->|"Sampled records"| E["Replay chain"] --> F["Emit table"]
  B -->|"Remaining records"| E
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Normalize iterpeek globally
  • ➕ Fixes the inconsistent single-item return contract at its source.
  • ➕ Could simplify other callers that need uniformly iterable samples.
  • ➖ May break callers relying on scalar results when peeking one item.
  • ➖ Expands the regression surface beyond dictionary and JSON-array handling.

Recommendation: Keep the PR’s localized islice and chain approach. It gives both regular and cached-generator paths identical sampling and replay behavior without changing the shared iterpeek contract or risking unrelated consumers.

Files changed (3) +63 / -4

Bug fix (1) +12 / -4
json.pyReplay sampled dictionaries after header discovery +12/-4

Replay sampled dictionaries after header discovery

• Replaces scalar-sensitive 'iterpeek' usage with a list collected through 'islice', then restores sampled records using 'chain'. Applies the behavior consistently to ordinary dictionary views and cached generator views, while documenting 'sample=1' and empty-input semantics.

petl/io/json.py

Tests (1) +48 / -0
test_json.pyCover sampled dictionary and JSON-array regressions +48/-0

Cover sampled dictionary and JSON-array regressions

• Adds parameterized coverage for list, iterator, and generator inputs with sample sizes 0, 1, and 2. Also verifies empty inputs, JSON arrays, later-discovered fields, record replay, and repeated iteration where supported.

petl/test/io/test_json.py

Documentation (1) +3 / -0
changes.rstDocument corrected single-record sampling behavior +3/-0

Document corrected single-record sampling behavior

• Adds an unreleased changelog entry noting preserved columns and values for 'sample=1', including safe handling of empty inputs.

docs/changes.rst

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Tip of the day
💡 Did you know, you can group findings by type and pick your Finding display, from Minimal to Full

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@coveralls

coveralls commented Sep 16, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 35546477051

Coverage increased (+0.02%) to 92.104%

Details

  • Coverage increased (+0.02%) from the base build.
  • Patch coverage: 37 of 37 lines across 2 files are fully covered (100%).
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 15527
Covered Lines: 14301
Line Coverage: 92.1%
Coverage Strength: 0.92 hits per line

💛 - Coveralls

@juarezr juarezr added the Usability Improvement that benefit petl usage for end users label Sep 21, 2026
@juarezr
juarezr merged commit 81245e4 into petl-developers:master Sep 21, 2026
30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Usability Improvement that benefit petl usage for end users

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants