Skip to content

feat: migrate map_walker.py + x12file.py producers to pyx12 codes (PR 4 of 6)#178

Merged
azoner merged 1 commit into
masterfrom
feat/walker-parser-pyx12-codes-pr4
May 6, 2026
Merged

feat: migrate map_walker.py + x12file.py producers to pyx12 codes (PR 4 of 6)#178
azoner merged 1 commit into
masterfrom
feat/walker-parser-pyx12-codes-pr4

Conversation

@azoner

@azoner azoner commented May 6, 2026

Copy link
Copy Markdown
Owner

Fourth slice of the X12 error code generalization plan. Walker and parser-time emissions now use pyx12 codes. With this slice, every producer in the codebase emits pyx12 codes; the legacy raw-X12 fallback in error_997 / error_999 / errh_json (added in PR 1) is no longer exercised — PR 5 removes it.

New pyx12 codes added to ERROR_CODES

  • SEG_5_SEGMENT_REPEAT_EXCEEDED — was incorrectly named SEG_4_* in PR 1; the walker emits \"5\" for segment-too-many, not \"4\". Fixed.
  • SEG_1_INVALID_SEG_ID — parser invalid segment id
  • SEG_1_LEADING_SPACE — parser leading whitespace
  • SEG_8_SEGMENT_EMPTY — parser empty segment

Producer migration

pyx12/map_walker.py (8 sites):

  • Segment usage='N': \"2\"SEG_2_SEGMENT_NOT_USED
  • Segment exceeds max repeat: \"5\"SEG_5_SEGMENT_REPEAT_EXCEEDED
  • Mandatory segment missing: \"3\"SEG_3_MANDATORY_SEGMENT_MISSING
  • Segment not found in map: \"1\"SEG_1_SEGMENT_NOT_FOUND
  • Mandatory loop missing: \"3\"SEG_3_MANDATORY_LOOP_MISSING
  • Loop usage='N': \"2\"SEG_2_LOOP_NOT_USED
  • Loop exceeds max repeat: \"4\"SEG_4_LOOP_REPEAT_EXCEEDED

pyx12/x12file.py (7 sites):

  • Empty segment: \"8\"SEG_8_SEGMENT_EMPTY
  • Invalid seg id: \"1\"SEG_1_INVALID_SEG_ID
  • Leading space: \"1\"SEG_1_LEADING_SPACE
  • Trailing element terminators: \"SEG1\"SEG_8_TRAILING_TERMINATORS
  • HL count mismatch: \"HL1\"SEG_8_HL_COUNT_MISMATCH
  • HL invalid parent: \"HL2\"SEG_8_HL_INVALID_PARENT
  • LX count mismatch: \"LX\"SEG_8_LX_COUNT_MISMATCH

The historical \"SEG1\"\"8\" inline visitor remap was already removed in PR 1's table-aware conversion. The SEG_8_TRAILING_TERMINATORS entry (ak/ik=\"8\") preserves the same output behavior. HL1/HL2/LX entries have ak_code=None/ik_code=None to preserve their historical "filtered out of ack" behavior.

Test updates

  • 7 test_x12file assertions migrated (parser-level codes)
  • 13 test_map_walker assertions migrated (walker-level codes)
  • All resJson fixtures regenerated; JSON channel now consistently carries pyx12 codes for every error level

Test plan

  • pytest pyx12/test/: 579 passed (no count change)
  • mypy --strict pyx12: clean (88 files)
  • ruff check + format --check: clean
  • res997/resAck fixtures unchanged (visitors translate at output)
  • resJson fixtures show pyx12 codes for every error level

🤖 Generated with Claude Code

… 4 of 6)

Fourth slice of the X12 error code generalization plan. Walker and
parser-time emissions now use pyx12 codes. With this slice, every
producer in the codebase emits pyx12 codes; the legacy raw-X12 fallback
in error_997 / error_999 / errh_json (added in PR 1) is no longer
exercised — PR 5 removes it.

Adds 5 new pyx12 codes to ERROR_CODES table to match producer paths:
- SEG_5_SEGMENT_REPEAT_EXCEEDED (was incorrectly named SEG_4_*; the
  walker emits "5" for segment-too-many, not "4")
- SEG_1_INVALID_SEG_ID (parser invalid segment id)
- SEG_1_LEADING_SPACE (parser leading whitespace)
- SEG_8_SEGMENT_EMPTY (parser empty segment)

Producer migration:

pyx12/map_walker.py (8 sites):
- Segment usage='N': "2" -> SEG_2_SEGMENT_NOT_USED
- Segment exceeds max repeat: "5" -> SEG_5_SEGMENT_REPEAT_EXCEEDED
- Mandatory segment missing (line 322): "3" -> SEG_3_MANDATORY_SEGMENT_MISSING
  (stored in MissingMandatorySeg buffer, flushed via line 491)
- Segment not found in map: "1" -> SEG_1_SEGMENT_NOT_FOUND
- Mandatory loop missing (line 524): "3" -> SEG_3_MANDATORY_LOOP_MISSING
- Loop usage='N': "2" -> SEG_2_LOOP_NOT_USED
- Loop exceeds max repeat: "4" -> SEG_4_LOOP_REPEAT_EXCEEDED

pyx12/x12file.py (7 sites):
- Empty segment: "8" -> SEG_8_SEGMENT_EMPTY
- Invalid seg id (lines 105, 364, 370): "1" -> SEG_1_INVALID_SEG_ID
- Leading space: "1" -> SEG_1_LEADING_SPACE
- Trailing element terminators: "SEG1" -> SEG_8_TRAILING_TERMINATORS
- HL count mismatch: "HL1" -> SEG_8_HL_COUNT_MISMATCH
- HL invalid parent: "HL2" -> SEG_8_HL_INVALID_PARENT
- LX count mismatch: "LX" -> SEG_8_LX_COUNT_MISMATCH

The historical "SEG1" -> "8" inline remap was already removed from the
visitors as part of PR 1's table-aware lookup conversion. The table
entry SEG_8_TRAILING_TERMINATORS (ak/ik="8") preserves the same output
behavior. HL1/HL2/LX entries have ak/ik=None to preserve their
historical "filtered out of ack" behavior.

Test updates:
- 7 test_x12file assertions migrated to expect pyx12 codes (parser
  test_trailing_ele_delim shared via inheritance accounted for the 14
  apparent failures from a single source change)
- 13 test_map_walker assertions migrated (walker error path tests)
- All resJson fixtures regenerated; the JSON channel now consistently
  carries pyx12 codes for every error level

Verification:
- pytest pyx12/test/: 579 passed (no count change)
- mypy --strict pyx12: clean (88 files)
- ruff check + format --check: clean

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@azoner azoner merged commit 23ac606 into master May 6, 2026
16 checks passed
@azoner azoner deleted the feat/walker-parser-pyx12-codes-pr4 branch May 6, 2026 04:01
azoner added a commit that referenced this pull request May 6, 2026
…179)

Fifth slice of the X12 error code generalization plan. Now that every
producer in the codebase emits pyx12 codes (PRs #175-#178), the legacy
raw-X12 fallback paths in the visitors and the validation tuples in
error_item.py are dead. This PR removes them and tightens
EleError/SegError __post_init__ to require ERROR_CODES keys.

Visitor changes:
- pyx12/error_999.py visit_seg / visit_ele: drop the valid_IK3_codes /
  valid_IK4_codes tuples and the elif fallback. Visitors now only do
  ERROR_CODES.get(err_cde) — None spec or None ik_code = drop.
- pyx12/error_997.py visit_seg / visit_ele: same shape, drop
  valid_AK3_codes / valid_AK4_codes tuples.

Validation tightening (pyx12/error_item.py):
- EleError.__post_init__: was `if err_cde not in ele_errors and err_cde
  not in ERROR_CODES: raise`. Now `if err_cde not in ERROR_CODES: raise`.
  Error message updated to point to pyx12.error_codes.ERROR_CODES.
- SegError.__post_init__: same shape change.
- The legacy seg_errors / ele_errors module-level tuples are removed.
  isa_errors stays (still used by ISAError validation; ISA-level codes
  are TA1 codes, not in scope of this refactor).

x12_code_for in error_codes.py keeps its permissive behavior of
falling through to err_cde for unknown codes — needed by the JSON
visitor for ISA/GS/ST envelope-level codes ("025", "010", etc.) which
aren't migrated to pyx12 codes (out of scope per the plan).

Test updates (test_error_item.py):
- All SegError/EleError construction tests migrated to pyx12 codes:
  "1" -> "SEG_1_segment_not_found", "8" -> "SEG_8_trailing_terminators",
  "1" -> "ELE_1_mandatory_missing", "10" -> "ELE_10_not_used", etc.
- Two new tests assert that legacy raw-X12 codes are now rejected:
  test_invalid_code_legacy_raw_X12_rejected on both SegError and
  EleError.

Verification:
- pytest pyx12/test/: 581 passed (579 + 2 new "legacy rejected" tests)
- mypy --strict pyx12: clean (88 files)
- ruff check + format --check: clean

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
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