[SYNPY-1875] Copy and deprecate copyWiki function - #1434
Open
andrewelamb wants to merge 2 commits into
Open
Conversation
andrewelamb
marked this pull request as draft
July 27, 2026 15:49
andrewelamb
marked this pull request as ready for review
July 27, 2026 16:00
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.
Problem:
synapseutils.copyWiki()was the only way to copy a wiki tree from one entity toanother, and it is legacy code that sits outside the object-oriented model layer:
synclient as its firstpositional argument, so it cannot be used from an async context and does not follow
the
synapse_clientkeyword pattern used everywhere else in the new API.entitySubPageId,destinationSubPageId,updateLinks,entityMap) that are inconsistent with the rest of the OOP models.WikiPagemodel, so users who have adoptedsynapseclient.modelshad to drop back down tosynapseutilsto copy a wiki —the same gap that was closed for
DownloadList,sync_to_synapse/sync_from_synapse, storage locations, and migration in earlier work.This is the
copyWikihalf of the ongoing migration ofsynapseutilsbulkoperations onto the object-oriented models (SYNPY-1875).
Solution:
Add
WikiPage.copy_async()(and its generated syncWikiPage.copy()) as theobject-oriented replacement for
copyWiki(), and deprecate the legacy function.New API function —
synapseclient/api/file_services.pyAdded
post_file_handles_copy(), wrappingPOST /filehandles/copy, used to copywiki attachment file handles to the destination. It batches requests by
MAX_FILE_HANDLE_PER_COPY_REQUESTinternally so callers do not have to, and it isre-exported from
synapseclient.api. This puts the file-handle-copy REST call in theapi/layer where the model can reuse it, rather than reimplementing the batchingthat
synapseutils.copyFileHandles()does.Deprecation —
synapseutils/copy_functions.pycopyWiki()is marked@deprecated(version="5.0.0")for removal in 6.0.0, with adocstring migration example pointing at
WikiPage.copy/WikiPage.copy_async. Thefunction itself is unchanged, so existing callers keep working.
Supporting changes
synapseclient/models/protocols/wikipage_protocol.py— synccopy()signatureadded so IDE type hints resolve.
docs/reference/experimental/sync/wiki.mdanddocs/reference/experimental/async/wiki.md—copy/copy_asyncadded to theWikiPagemembers lists so mkdocstrings generates the anchors and[synapseclient.models.WikiPage.copy]cross-references resolve.The orchestration is split into small module-level helpers
(
_validate_and_format_copy_inputs,_copy_wiki_pages,_collect_wiki_sub_tree_headers,_update_internal_links,_update_synapse_id_references,_ensure_destination_has_no_root_wiki,_get_existing_destination_wiki_page) so each piece is unit-testable withoutstanding up a full wiki tree.
Testing:
Unit tests —
tests/unit/synapseclient/models/async/unit_test_wiki_async.pyAdded a
TestWikiPageCopyclass coveringcopy_asyncend to end with mocks, plus atest class per helper. Coverage includes:
owner_id, invaliddestination_owner_id, invalidentity_mapkeys and values, non-numeric sub-page IDs.entity_sub_page_idraisesValueError, sub-page ID given for a source with nowiki raises
ValueError, sub-page ID type coercion.destination_sub_page_id, nonexistentdestination_sub_page_id, and errorpropagation from the destination-page and header-tree lookups.
update_linksonly (the default),entity_maponly, both, and neither.
non-mutation of the input headers, link and Synapse-ID rewriting across every
copied page,
Nonemarkdown becoming an empty string, and hierarchy preservationin
_copy_wiki_pagesincluding the create-under and write-into destination cases.Integration tests —
tests/integration/synapseclient/models/async/test_wiki_async.pyAdded a
TestWikiPageCopyclass that copies against a real Synapse backend:test_copy_entire_wiki_tree— full tree copy, verifying hierarchy, markdown,attachments, and rewritten internal links.
test_copy_wiki_sub_tree— copying only the sub-tree rooted at a given page.test_copy_wiki_into_existing_destination_page— copying into an existingdestination wiki page via
destination_sub_page_id.test_copy_wiki_from_entity_without_wiki— source with no wiki returns an emptylist.