Repository navigation
Follow inserted, deleted and moved columns in diff and merge - #4
Open
thisiseesmaeel wants to merge 3 commits into
Open
thisiseesmaeel wants to merge 3 commits into
thisiseesmaeel wants to merge 3 commits into
Conversation
The row code (alignment by content, the map from base rows to where they went, formula renumbering) was index arithmetic that didn't care which axis it ran on, so it now takes one: _by_line, _shape, _align, _aligned_diff, AxisMap and axis_map work on rows or columns, and rewrite_refs moves column letters under a column map the way it moves row numbers under a row map (cell refs with any $ mix, ranges that shrink or become #REF!, whole-column B:D, cross-sheet and from other sheets, named ranges through merge_names). Diffs show "column inserted / deleted / moved" lines, with full coordinates in the summary, and pick whichever of plain, rows or columns reads shortest. The text output's kind column grows from 14 to 15 characters to fit "column inserted". The merge follows one branch's column changes exactly as it follows row changes, and merges cell by cell, with a note, when both branches moved lines on a sheet or one branch moved both rows and columns. Two things the row path left alone are now handled on both axes: a table's range on the branch that didn't move lines is moved before the three-way, so "they insert a column inside the table, we add a row" merges; and a chart or pivot that branch edited, pointing at a moved sheet, is flagged as a conflict instead of coming over silently with stale ranges.
The row machinery (its own regex-based formula shifter, the op that rewrites sheet XML the way Excel would, the expectation worked out from the lines xlgit matched) takes an axis. Column shifts also move <cols> widths along and match whole-column refs.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Rows have been followed through diff and merge since 0.1; the README said "Inserted columns show as changed cells for now." This makes columns work the same way, through the same code.
column inserted,column deleted,column movedandcolumns inserted/deleted(empty ones) lines, with the column's cells summarised by full coordinate (D1: 'Gas', D2: 60, …). A sheet's diff is whichever of plain cells, rows or columns reads shortest. Markdown (PR comment) and the HTML view show them too: an inserted or moved column gets a marked header and cells, a deleted one a note line.B2,$B$2,B$2,$B2), ranges (B2:D9, shrinking or#REF!), whole-column refs (B:D,SUM(#REF!)when deleted), cross-sheet refs ('Other Sheet'!C3), refs on other sheets pointing at the shifted sheet, and defined names all follow. An edit to a cell in a column the other branch deleted is a conflict; clearing it agrees with the deletion.Design
Everything the row path did was index arithmetic that didn't care which axis it ran on, so it now takes an
Axis(ROW/COL: the event words, the Excel limit, the anchor line for formula shapes, how to split and build a coordinate)._by_row→_by_line,_shapeanchors on the axis,_align/_aligned_diffare unchanged in logic,RowMap→AxisMap(withmove(coord)andmove_ref(range)),row_map→axis_map(same gates: the aligned reading must be shorter than plain and must line up strictly more base cells than leaving every line in place).rewrite_refskeeps its shape;_move_refdispatches on the map's axis. Bare column letters only count as a whole-column ref inside a two-part range (B:D), because openpyxl's tokenizer labels names likeTaxas range operands too.plan_rows→plan_movescomputes both maps per sheet and branch and applies the rules above.merge_sheetmaps coordinates withAxisMap.move.merge_table_xmltakes the sheet's map.flag_stale_rangesreports taken charts (by the sheets their<c:f>series point at) and pivot bundles (by their worksheet source and the sheet they sit on).Nothing is duplicated: the row tests pass unchanged through the generalised code, and
row_map/row_op_eligible/verify_rowsremain as one-line wrappers.Limitations remaining
=B2+C2in column D becoming=B2+D2in E after an insert at C) shows as a changed cell in the diff, exactly as=SUM(D2:D6)→=SUM(D2:D7)does for rows.Follow-ups I'd be happy to do, if wanted
How it was tested
tests/test_cols.py: diff lines for inserted, deleted, moved and empty columns; plain edits stay cell by cell; text, markdown and HTML output.tests/test_col_merge.py: theirs inserts a column and ours edits to its right (both ways round); theirs deletes a column and ours edits another column; ours edits a cell in the deleted column → conflict; clearing it agrees; a clash keeps your value in the right column; both branches change columns → cell by cell; rows on one branch and columns on the other → cell by cell; rows and columns on one branch → cell by cell; the row merge still works; every reference form above, for an insert and a delete, on the shifted sheet, from another sheet and in a defined name, with each branch as the mover.tests/test_col_objects.py, through realgit mergewith the driver installed: a chart, a table and a defined name survive a column insert (both ways round); a table widened by one branch and extended by the other comes out with both; a chart edited on the other branch is flagged.fuzz/merge_fuzz.py --mode cols(new) and--mode rows, over the ~1,000 workbooks from the open-source test suites (fetch_corpus.sh --no-enron), two random edits per file, with--mode rowsonmainrun on the same sample and seed as a baseline:main.--mode cols, 996 files × 2 rounds (1,988 of 1,992 runs completed; the harness hung on the last four files): 304 ok / 0 fail, column change recognised exactly in 130, 1,684 skipped (sheet too complex for the harness's own column shifter, too small, or unreadable input).--mode rowson a 400-file sample, this branch vsmain(same files, same seed): 80 ok / 0 fail, row change recognised exactly in 36, and identical status, recognition and conflict count on every single run, so the shared code did not change row behaviour.