Skip to content

Convert USFM versification before updating from rows - #390

Merged
Enkidu93 merged 4 commits into
mainfrom
claude/issue-369-20261001-1520
Oct 9, 2026
Merged

Enkidu93 merged 4 commits into
mainfrom
claude/issue-369-20261001-1520

Conversation

@claude

@claude claude Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Quick summary

ParatextProjectTextUpdaterBase.update_usfm now converts the source USFM to the rows' versification before applying the update, so rows in one versification update a project in another. The conversion runs only when the two differ, so same-versification updates behave as before. Nothing in machine/jobs is touched.

Where to look

  • Chapter, book and verse-range remapping, plus heading and paragraph placement across chapter breaks: the 25 tests in tests/corpora/test_convert_usfm_versification_handler.py.
  • The updater switching versification only when it differs: test_update_usfm_converts_to_rows_versification.
  • DefaultParatextProjectSettings in the test utils now defaults to English, not Original, matching ScriptureRef. With the old default, 8 existing update tests started converting and failed.
  • ConvertUsfmVersificationHandler is a new export of machine.corpora. get_rows_versification is a new module-level function in update_usfm_parser_handler.py.

Validation

  • ./local_check.sh --agent-strict -- 873 passed, 3 skipped (local run, not CI-equivalent)

Issue / porting context

Closes #369
Closes #382

Ports sillsdev/machine#472 and sillsdev/machine#521.

🤖 Generated with Claude Code


This change is Reviewable

@ddaspit

ddaspit commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

@claude The CI failed for this PR. Fix it.

ddaspit added a commit that referenced this pull request Oct 1, 2026
The job only ran when the issue or PR author was an owner, member or
collaborator. The bot's association is NONE, so a member's @claude comment on
a PR Claude opened was skipped, as on #390. PRs authored by claude[bot] now
pass that check. The commenter must still be a member.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ddaspit added a commit that referenced this pull request Oct 1, 2026
The job only ran when the issue or PR author was an owner, member or
collaborator. The bot's association is NONE, so a member's @claude comment on
a PR Claude opened was skipped, as on #390. PRs authored by claude[bot] now
pass that check. The commenter must still be a member.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@ddaspit

ddaspit commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

@claude The CI build failed for this PR. Fix it.

@claude

claude Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor Author

Claude finished @ddaspit's task in 2m 16s —— View job


CI fix pushed

The Lint with pyright step failed. ConvertUsfmVersificationHandler.chapter declares alt_number and pub_number as Optional[str]. It calls ScriptureRefUsfmParserHandlerBase.chapter, which declared them as str.

I changed the base signature to Optional[str]. That matches UsfmParserHandler.chapter and the base class's own verse. The fix is commit 515e732.

Verification

  • pyright machine/corpora tests/corpora reports 0 errors.
  • black --check and flake8 are clean.
  • pytest tests/corpora gives 299 passed, 3 skipped.
  • ./local_check.sh --agent-strict did not complete here. It stopped while collecting the huggingface tests, with an ImportError for is_offline_mode in the local environment. Those tests are not touched by this change. The full pyright run also lists errors in the huggingface modules, which come from the same environment mismatch. The only pyright errors in this PR's files were the two I fixed.

The CI run was cancelled after the pyright failure, so I haven't seen the other CI jobs finish. Please check the new run.
· branch claude/issue-369-20261001-1520

@codecov-commenter

codecov-commenter commented Oct 1, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.67742% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 92.16%. Comparing base (cc99576) to head (b7ce280).

Files with missing lines Patch % Lines
...hine/corpora/convert_usfm_versification_handler.py 99.28% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #390      +/-   ##
==========================================
+ Coverage   92.07%   92.16%   +0.09%     
==========================================
  Files         394      396       +2     
  Lines       24896    25199     +303     
==========================================
+ Hits        22922    23225     +303     
  Misses       1974     1974              

☔ 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.

ddaspit added a commit that referenced this pull request Oct 1, 2026
A push by the @claude workflow makes claude[bot] the actor, and
claude-code-action rejects a bot actor unless it is listed in allowed_bots.
The review of #390 failed this way. The review never pushes, so allowing
Claude cannot make it retrigger itself.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@ddaspit
ddaspit force-pushed the claude/issue-369-20261001-1520 branch from 515e732 to 7bc8382 Compare October 1, 2026 18:09
Comment thread machine/corpora/convert_usfm_versification_handler.py
Comment thread machine/corpora/convert_usfm_versification_handler.py
Comment thread machine/corpora/convert_usfm_versification_handler.py
Comment thread machine/corpora/paratext_project_text_updater_base.py
@claude

This comment has been minimized.

@ddaspit

ddaspit commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

@claude Address all of the review comments, except those that would result in the PR diverging from the original C# code.

@claude

claude Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor Author

Claude finished @ddaspit's task in 17s —— View job


No code changes made

I made no changes and pushed no commits. Every review comment falls under your exception, because a fix would make the Python port differ from the C# code.

  • F1 (convert_usfm_versification_handler.py:170): a split range at the end of the input writes the verse text twice. The review says C# EndUsfm has the same shape, so I left it. A fix here would diverge from C#.
  • F2 (:163): markers after the last verse are dropped. The review says C# shares this, so I left it.
  • F3 (:58): a chapter with no verses loses its \c. The review says C# shares this, so I left it.
  • F4 (paratext_project_text_updater_base.py:68): with no rows, get_rows_versification returns English. This matches C# GetRowsVersification. Skipping the conversion would be a deliberate divergence, so I left it.

Not verified: I could not read the C# source in this session, because the gh api and WebFetch calls were denied. I am relying on the review's statement that C# behaves the same way for all four. The Python code has not been run for F1–F3 either, since those findings were hand traces.

Suggested follow-up: F1–F3 look like real defects. If you want them fixed, they could go upstream in sillsdev/machine first, and then be ported here. Tell me if you would rather fix them here and accept the divergence.
· branch claude/issue-369-20261001-1520

ddaspit added a commit that referenced this pull request Oct 1, 2026
port-pr reads the C# code from a sibling clone at ../machine, which the
@claude workflow never created, so Claude could not check C# behavior on #390.
The workflow now clones sillsdev/machine with full history. Claude can read it
and run git show, cat-file, log and blame there.

port-pr reads each C# file as of the source PR's merge commit. It checks that
the commit exists first and fetches when a local clone is stale.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@ddaspit
ddaspit force-pushed the claude/issue-369-20261001-1520 branch from 7bc8382 to aa0d660 Compare October 1, 2026 20:40
@ddaspit

ddaspit commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

@claude You should now be able to read the C# source.

@claude

claude Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor Author

Claude finished @ddaspit's task in 18s —— View job


No code changes made

I read the C# source (ConvertUsfmVersificationHandler.cs and ParatextProjectTextUpdaterBase.cs in sillsdev/machine) and compared it with this PR. The Python matches it on all four review findings, so fixing any of them here would make the port diverge. I pushed no commits.

  • F1 (convert_usfm_versification_handler.py:170): C# EndUsfm (lines 229-235) appends state.Token unconditionally when _skip is false and the token is not a chapter or verse. The Python end_usfm does the same. C# Verse also adds the next text token in the split-range branches (lines 156-165, 177-186), as _add_next_text_token does. The double write on an input that ends on a split range is therefore in C# too. I did not run it.
  • F2 (:163): C# EndUsfm calls ProcessTokens and never AddTrailingTokens, so markers after the last verse are dropped there as well.
  • F3 (:58): C# Chapter only sets _insertChapterIndex = _tokens.Count (line 58). It emits \c only from Verse, so a chapter with no verses loses its \c in C# too.
  • F4 (paratext_project_text_updater_base.py:68): C# UpdateUsfmParserHandler.GetRowsVersification(rows) feeds the same rowsVersification != _settings.Versification check (lines 69-77). The Python is the same.

F1-F3 look like real defects in the C# original. I'd fix them upstream in sillsdev/machine and then port the fix here. If you'd rather fix them in this PR and accept the divergence, tell me and I will. I would also add an empty-chapter test for F3 in either case.
· branch claude/issue-369-20261001-1520

Comment thread machine/corpora/convert_usfm_versification_handler.py
@claude

This comment has been minimized.

@ddaspit

ddaspit commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

@claude Fix F5 if it doesn't diverge from the C# source.

@claude

claude Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor Author

Claude finished @ddaspit's task in 21s —— View job


No code changes made for F5

I left F5 alone because fixing it would make the Python port differ from the C# code. I pushed no commits.

  • C# ConvertUsfmVersificationHandler.ProcessTokens (ConvertUsfmVersificationHandler.cs:243-271) matches Python _process_tokens line for line. Both copy every token up to state.Index and then set _verseBoundary = state.Index + 1. Neither treats \ca/\cp specially, so a merged chapter's \ca 5\ca* is copied at the next call.
  • C# Chapter only sets _insertChapterIndex, the same as Python. It never drops the alternate-number tokens.

I read the C# source and compared it by hand. I did not run the Python on the F5 input.

F5 looks like a real defect in C#. I'd fix it upstream in sillsdev/machine and then port the fix here. If you'd rather fix it in this PR and accept the divergence, tell me and I will. I'd add a test for the \ca case either way.
· branch claude/issue-369-20261001-1520

@Enkidu93 Enkidu93 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Enkidu93 reviewed 8 files and all commit messages, and made 2 comments.
Reviewable status: all files reviewed, 3 unresolved discussions.


machine/corpora/convert_usfm_versification_handler.py line 15 at r1 (raw file):

def _change_versification(verse_ref: VerseRef, versification: Versification) -> VerseRef:

Just use the built-in to_versificationmethod.


tests/corpora/test_convert_usfm_versification_handler.py line 762 at r1 (raw file):

    target_lines = target.split("\n")
    truth_lines = truth.split("\n")
    for i, truth_line in enumerate(truth_lines):

We ought to assert that there are an equal number of target and truth lines.

@ddaspit

ddaspit commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

@claude Address the comments.

@claude

claude Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor Author

Claude finished @ddaspit's task in 27s —— View job


Addressed Enkidu93's review comments

I pushed commit d685e2a, but I could not run the tests, black, flake8 or ./local_check.sh --agent-strict. Each needed approval this session lacked. Please check the new CI run.

  • _change_versification helper (convert_usfm_versification_handler.py): I removed the helper and call vr.to_versification(self._target_versification) in both places.
    • to_versification raises ValueError when a ref cannot be converted. The old helper ignored that failure and kept the unconverted ref. If a test fails, this is the likely cause.
    • The imports are still used, so flake8 should not complain.
  • Line-count assertion (test_convert_usfm_versification_handler.py): assert_usfm_equals now asserts that the target and truth have the same number of lines before comparing them line by line.
    · branch claude/issue-369-20261001-1520

ddaspit added a commit that referenced this pull request Oct 6, 2026
On #390, Claude could not run the tests or local_check.sh, although both are
allowed. The action hides Claude's output, so the log only gave a count of 3
denials. A new step prints the denied calls from the execution file.

Allowed commands match by prefix, so the prompt now asks Claude to run the
checks from the repository root without cd or a wrapper. tail and head are
allowed for trimming output.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ddaspit added a commit that referenced this pull request Oct 6, 2026
On #390, Claude could not run the tests or local_check.sh, although both are
allowed. The action hides Claude's output, so the log only gave a count of
denials. A new step prints each denied call's command, path, URL or pattern as
one JSON line. It never prints file content and cannot fail the job.

Allowed commands match by prefix, so the prompt now asks Claude to run the
checks from the repository root without cd or a wrapper. tail and head are
allowed for trimming output.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

@Enkidu93 Enkidu93 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@claude The CI is failing when running black:


Run poetry run black . --check --diff
Skipping .ipynb files as Jupyter dependencies are not installed.
You can fix this by running ``pip install "black[jupyter]"``
--- D:\a\machine.py\machine.py\machine\corpora\convert_usfm_versification_handler.py	2026-10-05 19:48:12.830494+00:00
+++ D:\a\machine.py\machine.py\machine\corpora\convert_usfm_versification_handler.py	2026-10-05 19:49:20.001164+00:00
@@ -43,12 +43,11 @@
would reformat D:\a\machine.py\machine.py\machine\corpora\convert_usfm_versification_handler.py
         self._process_tokens(state)
         vr = state.verse_ref.copy()
         # The versification of verse 0 cannot properly be changed
         vr.verse = "1"
         if not self._prev_verse_ref.is_default and (
-            vr.to_versification(self._target_versification).book != self._prev_verse_ref.book
-            or vr.chapter_num == -1
+            vr.to_versification(self._target_versification).book != self._prev_verse_ref.book or vr.chapter_num == -1
         ):
             self._skip = True
         self._insert_chapter_index = len(self._tokens)
 
     def verse(

Oh no! \U0001f4a5 \U0001f494 \U0001f4a5
1 file would be reformatted, 413 files would be left unchanged.

@Enkidu93 reviewed 2 files and all commit messages, made 3 comments, resolved 2 discussions, and dismissed @Enkidu93 from 2 discussions.
Reviewable status: all files reviewed, 1 unresolved discussion.


machine/corpora/convert_usfm_versification_handler.py line 15 at r1 (raw file):

Previously, Enkidu93 (Eli C. Lowry) wrote…

Just use the built-in to_versificationmethod.

Done.


tests/corpora/test_convert_usfm_versification_handler.py line 762 at r1 (raw file):

Previously, Enkidu93 (Eli C. Lowry) wrote…

We ought to assert that there are an equal number of target and truth lines.

Done.

@claude

claude Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor Author

Claude finished @Enkidu93's task in 21s —— View job


Black fix pushed

I ran black on machine/corpora/convert_usfm_versification_handler.py. It joined the to_versification(...) condition onto one line, as in your CI diff. I pushed this as commit 7db6e13.

poetry run black . --check now reports all 414 files unchanged. I did not run flake8, pyright, pytest or ./local_check.sh --agent-strict, so please check the new CI run for those.
· branch claude/issue-369-20261001-1520

@claude

This comment has been minimized.

github-actions Bot and others added 4 commits October 7, 2026 13:08
Port sillsdev/machine#472 and the follow-up fixes from sillsdev/machine#521.
ParatextProjectTextUpdaterBase.update_usfm now converts the source USFM to the
rows' versification when it differs from the project's, using the new
ConvertUsfmVersificationHandler.

The test project settings now default to English versification, matching
ScriptureRef, so existing update tests do not trigger a conversion.

Closes #369
Closes #382

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Damien Daspit <3261883+ddaspit@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Damien Daspit <3261883+ddaspit@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Damien Daspit <3261883+ddaspit@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Eli C. Lowry <83078660+Enkidu93@users.noreply.github.com>
@Enkidu93
Enkidu93 force-pushed the claude/issue-369-20261001-1520 branch from 7db6e13 to b7ce280 Compare October 7, 2026 17:08
@claude

claude Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author
  1. Verdict: approve. Since the last round the PR was only rebased; its code did not change.
  2. Most important: none new. F1 (machine/corpora/convert_usfm_versification_handler.py:170) is still the worst known defect: a split range at the end of the input has its text written twice. It is accepted for C# parity.
  3. Counts: 0 Critical, 0 Important, 0 Low new. F1-F5 are all accepted.
  4. Ran: gh api compare 7db6e13...b7ce280 returned diverged, so history was rewritten. I compared the blob SHAs of all 8 PR files at both commits through the GraphQL tree API, and all 8 match. The new base differs from the old one only in .github/workflows. I did not rerun /code-review, because the content is identical to the code earlier rounds reviewed. pytest tests/corpora tests/scripture: 369 passed, 3 skipped. black --check machine/corpora tests/corpora tests/testutils: clean. pyright machine/corpora tests/corpora: 0 errors.
  5. Not verified: ./local_check.sh --agent-strict was denied approval in this session, so the full suite and flake8 were not run. F1-F3 and F5 are still hand traces.

API surface: unchanged since the last round. ConvertUsfmVersificationHandler is a new export of machine.corpora. update_usfm now returns USFM in the rows' versification, matching sillsdev/machine#472 and #521.

Findings: F1 accepted, unverified. F2 accepted, unverified. F3 accepted, unverified. F4 accepted. F5 accepted, unverified.

Reviewed at b7ce280

@Enkidu93 Enkidu93 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm:

@Enkidu93 reviewed 1 file and all commit messages, and made 1 comment.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on claude[bot]).

@Enkidu93
Enkidu93 merged commit e276d06 into main Oct 9, 2026
21 checks passed
@Enkidu93
Enkidu93 deleted the claude/issue-369-20261001-1520 branch October 9, 2026 18:00
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.

Port 'Fix double mappings handling and expand trailing paragraph marker definition' Port 'Convert USFM versification'

3 participants