Skip to content

feat: support nested objects - #18

Merged
Chris1221 merged 6 commits into
mainfrom
support-nested-objects
Jul 4, 2026
Merged

feat: support nested objects#18
Chris1221 merged 6 commits into
mainfrom
support-nested-objects

Conversation

@Chris1221

@Chris1221 Chris1221 commented Aug 8, 2024

Copy link
Copy Markdown
Owner

Summary

Adds support for arbitrarily nested YAML objects in yamldoc documentation output.

What changed

  • Parser (parser.py): Replaced flat single-level sub-entry handling with a context stack (sub_stack) that routes new entries to the correct parent MetaEntry at any indentation depth.
  • Entries (entries.py):
    • MetaEntry now has a type attribute (for schema-derived type info) and a to_table_row() method for inline rendering within a parent table.
    • MetaEntry.to_markdown() takes a depth parameter and uses depth-aware heading levels (##/### at depth 1, ####/##### at depth 2), then recursively renders nested MetaEntries beneath the table.
  • Schema resolution (add_type_metadata): Recursive tree search replaces the previous 2-level-only approach, so schema types are applied correctly regardless of nesting depth.
  • Tests: Added fixture files (deeper_nesting.yaml, deeper_nesting.schema, deeper_nesting_exclusion.yaml) and full test coverage for 3-level nesting (parse, schema, E2E, markdown output, exclusion).
  • README: Removed stale CircleCI badge; updated codecov badge to main branch.

Rendered output for 3-level nesting

Given:

#' This is a three level thing.
three:
    #' This is the second level.
    level_two:
        #' This is the third level.
        level_three: "hello"

Produces:

## `three`

This is a three level thing.

### Member variables:

| Key | Value | Type | Information |
| :-: | :-: | :-: | :-- |
| `level_two` |  | object | This is the second level. |

#### `level_two`

This is the second level.

##### Member variables:

| Key | Value | Type | Information |
| :-: | :-: | :-: | :-- |
| `level_three` | `"hello"` | string | This is the third level. |

Test plan

  • All 44 existing tests pass
  • TestYAMLs::test_deeper_nesting — parses 3-level structure correctly
  • TestSchemas::test_deeper_nesting — schema types applied at depth 3
  • TestE2E::test_deeper_nesting — all keys/values present in output
  • TestMarkdown::test_deeper_nesting — exact markdown output matches expected
  • test_deeper_nesting_exclusion — nested exclusion works correctly

🤖 Generated with Claude Code

@Chris1221
Chris1221 changed the base branch from master to main July 4, 2026 15:54
Chris1221 and others added 2 commits July 4, 2026 12:13
Related to #14

Add support for arbitrary levels of nesting in `yamldoc`.

* **Documentation Updates**
  - Update `docs/hier_tutorial.md` to reflect support for arbitrary levels of nesting.
  - Update `README.md` to remove the note about the two-level nesting limitation.

* **Code Changes**
  - Modify `yamldoc/parser.py` to handle arbitrary levels of nesting.
  - Update `yamldoc/parser.py` to add type metadata for deeper nested entries.

* **Test Updates**
  - Add new test cases in `test/test_examples.py` for deeper nesting.
  - Add new test cases in `test/test_exclude.py` for deeper nesting exclusion.
  - Update `test/yaml/two_level.yaml` and `test/schema/two_level.schema` to include examples of deeper nesting.

---

For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/Chris1221/yamldoc/issues/14?shareId=XXXX-XXXX-XXXX-XXXX).
Implements context-stack parser for routing sub-entries to the correct
parent MetaEntry at any nesting depth, replacing the flat single-level
approach. Nested MetaEntries now render as table rows within their
parent section plus a deeper heading section (#### / #####).

Also fixes add_type_metadata to search the full YAML tree recursively
so schema types are applied correctly at any depth.

Adds test fixtures for deeper nesting (three levels) and updates
the exclusion test to cover nested exclusion. Removes the stale
CircleCI badge from README and updates codecov badge to main branch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Chris1221
Chris1221 force-pushed the support-nested-objects branch from a1dc79b to 95e1c4b Compare July 4, 2026 17:44
@codecov

codecov Bot commented Jul 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.29730% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.61%. Comparing base (f7d9112) to head (a0688b6).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
yamldoc/parser.py 92.68% 3 Missing ⚠️
yamldoc/entries.py 96.55% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #18      +/-   ##
==========================================
+ Coverage   90.52%   91.61%   +1.08%     
==========================================
  Files           7        7              
  Lines         665      787     +122     
==========================================
+ Hits          602      721     +119     
- Misses         63       66       +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Chris1221
Chris1221 marked this pull request as ready for review July 4, 2026 18:20
@Chris1221 Chris1221 changed the title Support nested objects feat: support nested objects Jul 4, 2026
@Chris1221

Copy link
Copy Markdown
Owner Author

@claude Please review

@claude

claude Bot commented Jul 4, 2026

Copy link
Copy Markdown

Claude finished @Chris1221's task in 3m 4s —— View job


Review complete

  • Gather context (PR diff, changed files, CLAUDE.md)
  • Understand the request (code review of nested objects support)
  • Review parser.py changes (sub_stack context)
  • Review entries.py changes (MetaEntry depth, to_table_row)
  • Review test coverage / fixtures
  • Check for stray committed artifacts (egg-info)
  • Post final review

Note: I could not execute pytest in this sandbox (python invocation was blocked by tooling permissions), so this review is based on static reading of the diff (git diff f7d9112..HEAD) and manual trace-through of the parsing/rendering logic, not a live test run.

The overall approach is solid: replacing the old 2-level-only sub-entry handling with a generic sub_stack in yamldoc/parser.py is a clean way to support arbitrary nesting depth, and the recursive _find_meta_entry search in add_type_metadata is a good simplification over the old flat lookup. Test coverage for the 3-level case (parse/schema/E2E/markdown/exclusion) is thorough.

Two things worth addressing:

1. Markdown heading levels overflow past 2 levels of nested MetaEntrys (yamldoc/entries.py:138-139)

h_section = "#" * (depth * 2)
h_members = "#" * (depth * 2 + 1)

At depth=3 (i.e. a 4th level of key nesting: top -> obj1 -> obj2 -> obj3), h_members becomes 7 # characters, which exceeds CommonMark's max heading level (h6) and will render as plain text instead of a heading. The PR title/commit message ("support arbitrary nesting depth in objects") implies unlimited depth, but only 2 levels of nested MetaEntrys render correctly — this is also called out honestly in the CLAUDE.md diff, but there's no test exercising a 4th level, so this regression-in-waiting isn't caught. Worth either capping heading levels (e.g. min(depth * 2 + 1, 6)) and falling back to bold text beyond that, or adding a test that documents/asserts the current 3-level ceiling if that's an accepted limitation for now.

Fix this →

2. yamldoc.egg-info/ build artifacts committed (introduced in 72ce0f3)

yamldoc.egg-info/PKG-INFO, SOURCES.txt, dependency_links.txt, entry_points.txt, top_level.txt are added by this PR, even though .gitignore already excludes *.egg-info/. These look like accidentally force-added local build artifacts rather than intentional changes.

Fix this →

Minor / non-blocking:

  • _find_meta_entry in yamldoc/parser.py does a pre-order search by name and returns the first match. If two different objects in the tree happen to share a key name (e.g. two.entry and three.entry), schema type resolution could apply the wrong type to the wrong node. Not exercised by current fixtures; probably fine for now given typical config-file key naming, but worth a comment or a path-qualified lookup if this becomes an issue in practice.

Nice work overall — the sub_stack design is the right fix for the previous 2-level ceiling, and the test fixtures (deeper_nesting.yaml/.schema, exclusion case) are well-targeted at the new code paths.

Chris1221 and others added 4 commits July 4, 2026 16:54
CommonMark only supports h1-h6; at nesting depth >= 3 the heading formula
`depth * 2` would produce 7+ hashes which renders as plain text. Now falls
back to bold text (**`name`** / **Member variables:**) for levels beyond h6.

Also removes yamldoc.egg-info/ from git tracking (already in .gitignore,
accidentally included from a prior rebase).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove leading newline from table_header() so Member variables tables
  don't have a blank line between the heading and the table
- Skip extra blank line in to_markdown() when a MetaEntry has no meta text
- Reduce nested section gap from 3 newlines to 1 so nested #### sections
  sit cleanly after their parent table row
- Add blank line separator in main() between the flat-entry table and the
  first MetaEntry section (## heading)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Using a heading level for "Member variables:" was wasteful — it consumed
a heading level at every nesting depth, accelerating the h6 overflow.
Switching to bold text (**Member variables:**) keeps the visual hierarchy
clear while leaving all heading levels for actual object names.

Adds TestSpacing regression suite (5 tests) that preserve newlines to
catch spacing regressions that the newline-stripping markdown tests miss:
- blank line between flat table and first section heading
- no extra blank line after the members label
- single blank line before nested sections
- no extra blank line for sections with empty meta
- no consecutive blank lines across multiple YAML files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
depth*2 jumped from ## straight to #### (skipping ###), making nested
sections look more deeply indented than they are. depth+1 increments
naturally: depth=1 → ##, depth=2 → ###, depth=3 → ####, up to h6 at
depth=5. Overflow to bold still kicks in at depth=6+.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Chris1221
Chris1221 merged commit fdccf8a into main Jul 4, 2026
4 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