Commit 5c7c149
fix(slides): unify master/layout id pool in append_from to clear PowerPoint repair
`Presentation.append_from` triggered PowerPoint's bad-content / repair
dialog on first open of any multi-master output. Three distinct OOXML
id collisions inherited from the shared default.pptx template needed
scrubbing during cross-package master/layout deepcopy:
1. `<p:sldMasterId id>` and `<p:sldLayoutId id>` share one identifier
pool per ECMA-376 sec 19.2.1.34 / 19.2.1.27, and PowerPoint enforces
uniqueness across both. The new master2 was being allocated id
2147483649 (one above target's lone master at 2147483648) — but
2147483649 was already master1's first layout id. PowerPoint's
repair output renumbered master2 to 2147483660. Root fix: build a
unified pool from BOTH master and layout ids in the target, allocate
master id first (consumes one slot), then renumber layout ids above
it. End state matches PowerPoint's repair ordering (master2=
2147483660, master2's layouts=2147483661..2147483671).
2. `<p:sldLayoutId id>` collided across masters because deepcopy of the
source master carried the source's layout ids verbatim, identical to
target's existing master's layout ids when both came from the same
default.pptx. Spec: unique within the layout collection; PowerPoint:
unique across the presentation.
3. `<p14:creationId val>` was deterministic in default.pptx (master:
2209977519, plus 11 fixed layout vals), so two presentations from
the template ended up with identical vals across their parallel
masters and layouts. Refresh each val to a fresh secrets.randbits(32)
on deepcopy to keep the extLst structure intact while breaking the
collision.
Diagnostic path: PowerPoint's repair dialog gave only the generic
"PowerPoint found a problem with content" with no error-line detail.
Iterated by having the maintainer save the repaired copy and diffing
against the original; the rewritten `<p:sldMasterId id>` value
(2147483649 → 2147483660) revealed the master/layout pool sharing.
Surface:
- src/pptx/parts/slide.py: new _used_master_layout_ids_in_target,
_renumber_sldLayoutIds, _refresh_creation_ids; _add_sldMasterId_to
_presentation accepts unified pool; _port_master and _port_layout
_standalone apply scrubs at deepcopy points
- tests/test_append_from.py: DescribePresentation_AppendFrom_OOXML
Integrity class with 4 zip-level integrity tests (sldLayoutId
uniqueness across masters, master id disjoint from layout id pool,
master creationId uniqueness, layout creationId uniqueness)
Refs #11.
Tests: 3166 unit (+4 new) + 994 behave scenarios all passing.
Lint: ruff check + ruff format clean.1 parent adb869c commit 5c7c149
2 files changed
Lines changed: 233 additions & 10 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| |||
293 | 294 | | |
294 | 295 | | |
295 | 296 | | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
296 | 300 | | |
297 | 301 | | |
298 | 302 | | |
| |||
382 | 386 | | |
383 | 387 | | |
384 | 388 | | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
385 | 396 | | |
386 | 397 | | |
387 | 398 | | |
| |||
512 | 523 | | |
513 | 524 | | |
514 | 525 | | |
| 526 | + | |
515 | 527 | | |
516 | 528 | | |
517 | 529 | | |
| |||
537 | 549 | | |
538 | 550 | | |
539 | 551 | | |
540 | | - | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
541 | 559 | | |
542 | 560 | | |
543 | 561 | | |
544 | 562 | | |
| 563 | + | |
545 | 564 | | |
546 | 565 | | |
547 | 566 | | |
| |||
550 | 569 | | |
551 | 570 | | |
552 | 571 | | |
| 572 | + | |
| 573 | + | |
553 | 574 | | |
554 | 575 | | |
555 | | - | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
556 | 582 | | |
557 | 583 | | |
558 | 584 | | |
| |||
567 | 593 | | |
568 | 594 | | |
569 | 595 | | |
| 596 | + | |
570 | 597 | | |
571 | 598 | | |
572 | 599 | | |
| |||
761 | 788 | | |
762 | 789 | | |
763 | 790 | | |
764 | | - | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| 807 | + | |
| 808 | + | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
| 816 | + | |
| 817 | + | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
| 822 | + | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
| 836 | + | |
| 837 | + | |
| 838 | + | |
| 839 | + | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
765 | 860 | | |
766 | 861 | | |
767 | 862 | | |
768 | 863 | | |
769 | 864 | | |
770 | 865 | | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
771 | 873 | | |
772 | 874 | | |
773 | | - | |
774 | | - | |
775 | | - | |
776 | | - | |
777 | | - | |
778 | | - | |
779 | | - | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
| 878 | + | |
| 879 | + | |
| 880 | + | |
| 881 | + | |
| 882 | + | |
780 | 883 | | |
781 | 884 | | |
782 | 885 | | |
| 886 | + | |
783 | 887 | | |
784 | 888 | | |
785 | 889 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
527 | 527 | | |
528 | 528 | | |
529 | 529 | | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
0 commit comments