-
Notifications
You must be signed in to change notification settings - Fork 72
[SYNPY-1351, SYNPY-1613] Implement 'Wiki2' model into OOP #1206
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 24 commits
fef882b
977413b
b2a5840
1ce73fd
0685de4
0fc3f75
d4a98e8
86fa041
6601fdc
b7289f2
21a4d8d
e06a35a
2fdfc71
176cdf8
c52996f
99cbb81
47f38e0
a620db5
4e89258
da4dfa4
be5aae4
1ab9888
082df85
43bb9a0
0a5f2e6
c6077e0
cef775b
e32da1b
50417a3
d59a9d6
a317bc9
9ae4c81
d52720c
cbcbf35
5c66880
d8055d6
9d923ff
b362230
02b509a
62f03d4
e56540e
a46417c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
#!/usr/bin/env python3 | ||
""" | ||
Tutorial script demonstrating the Synapse Wiki models functionality. | ||
|
||
This script shows how to: | ||
1. Create, read, and update wiki pages | ||
2. Work with WikiPage Markdown | ||
3. Work with WikiPage Attachments | ||
4. Work with WikiHeader | ||
5. Work with WikiHistorySnapshot | ||
6. Work with WikiOrderHint | ||
7. Delete wiki pages | ||
""" | ||
import gzip | ||
import os | ||
import uuid | ||
|
||
from synapseclient import Synapse | ||
from synapseclient.models import ( | ||
Project, | ||
WikiHeader, | ||
WikiHistorySnapshot, | ||
WikiOrderHint, | ||
WikiPage, | ||
) | ||
|
||
# Initialize Synapse client | ||
syn = Synapse() | ||
syn.login() | ||
|
||
# Create a Synapse Project to work with | ||
my_test_project = Project( | ||
name=f"My Test Project_{uuid.uuid4()}", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check out the other tutorials created. There is a theme around a project for alzheimer's disease that i had been following. The tutorial is great, and covers everything one would care to do. Let's see if we can tweak the theme of the content just a bit. |
||
description="This is a test project for the wiki tutorial.", | ||
).store() | ||
print(f"Created project: {my_test_project.name} with ID: {my_test_project.id}") | ||
|
||
# Section1: Create, read, and update wiki pages | ||
# Create a new wiki page for the project with plain text markdown | ||
wiki_page_1 = WikiPage( | ||
owner_id=my_test_project.id, | ||
title="My Root Wiki Page", | ||
markdown="# Welcome to My Root Wiki\n\nThis is a sample root wiki page created with the Synapse client.", | ||
).store() | ||
|
||
# OR you can create a wiki page with an existing markdown file | ||
markdown_file_path = "path/to/your_markdown_file.md" | ||
wiki_page_1 = WikiPage( | ||
owner_id=my_test_project.id, | ||
title="My First Root Wiki Page Version with existing markdown file", | ||
markdown=markdown_file_path, | ||
).store() | ||
|
||
# Create a new wiki page with updated content | ||
wiki_page_2 = WikiPage( | ||
owner_id=my_test_project.id, | ||
title="My First Root Wiki Page Version 1", | ||
markdown="# Welcome to My Root Wiki Version 1\n\nThis is a sample root wiki page created with the Synapse client.", | ||
id=wiki_page_1.id, | ||
).store() | ||
|
||
# Restore the wiki page to the original version | ||
wiki_page_restored = WikiPage( | ||
owner_id=my_test_project.id, id=wiki_page_1.id, wiki_version="0" | ||
).restore() | ||
|
||
# check if the content is restored | ||
comparisons = [ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is probably easier and cleaner to use assert statements here. Like
That was if it does fail, it's clear which one failed the compare check |
||
wiki_page_1.markdown_file_handle_id == wiki_page_restored.markdown_file_handle_id, | ||
wiki_page_1.id == wiki_page_restored.id, | ||
wiki_page_1.title == wiki_page_restored.title, | ||
] | ||
print(f"All fields match: {all(comparisons)}") | ||
|
||
# Create a sub-wiki page | ||
sub_wiki = WikiPage( | ||
owner_id=my_test_project.id, | ||
title="Sub Wiki Page 1", | ||
parent_id=wiki_page_1.id, # Use the ID of the parent wiki page we created '633033' | ||
markdown="# Sub Page 1\n\nThis is a sub-page of another wiki.", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Out of curiosity. If you use a multi-line python string:
Does that automatically add in the newline characters? Or are you forced to use the |
||
).store() | ||
|
||
# Get an existing wiki page for the project, now you can see one root wiki page and one sub-wiki page | ||
wiki_header_tree = WikiHeader.get(owner_id=my_test_project.id) | ||
print(wiki_header_tree) | ||
|
||
# Once you know the wiki page id, you can retrieve the wiki page with the id | ||
retrieved_wiki = WikiPage(owner_id=my_test_project.id, id=sub_wiki.id).get() | ||
print(f"Retrieved wiki page with title: {retrieved_wiki.title}") | ||
|
||
# Or you can retrieve the wiki page with the title | ||
retrieved_wiki = WikiPage(owner_id=my_test_project.id, title=wiki_page_1.title).get() | ||
print(f"Retrieved wiki page with title: {retrieved_wiki.title}") | ||
|
||
# Check if the retrieved wiki page is the same as the original wiki page | ||
comparisons = [ | ||
wiki_page_1.markdown_file_handle_id == retrieved_wiki.markdown_file_handle_id, | ||
wiki_page_1.id == retrieved_wiki.id, | ||
wiki_page_1.title == retrieved_wiki.title, | ||
] | ||
print(f"All fields match: {all(comparisons)}") | ||
|
||
# Section 2: WikiPage Markdown Operations | ||
# Create wiki page from markdown text | ||
markdown_content = """# Sample Markdown Content | ||
|
||
## Section 1 | ||
This is a sample markdown file with multiple sections. | ||
|
||
## Section 2 | ||
- List item 1 | ||
- List item 2 | ||
- List item 3 | ||
|
||
## Code Example | ||
```python | ||
def hello_world(): | ||
print("Hello, World!") | ||
``` | ||
""" | ||
|
||
# Create wiki page from markdown text | ||
markdown_wiki_1 = WikiPage( | ||
owner_id=my_test_project.id, | ||
parent_id=wiki_page_1.id, | ||
title="Sub Page 2 created from markdown text", | ||
markdown=markdown_content, | ||
).store() | ||
|
||
# Create a wiki page from a markdown file | ||
# Create a temporary markdown gzipped file from the markdown_content | ||
markdown_file_path = "temp_markdown_file.md.gz" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In most of the tutorials we have been using the "~/temp` directory to write files to |
||
with gzip.open(markdown_file_path, "wt", encoding="utf-8") as gz: | ||
gz.write("This is a markdown file") | ||
|
||
# Create wiki page from markdown file | ||
markdown_wiki_2 = WikiPage( | ||
owner_id=my_test_project.id, | ||
parent_id=wiki_page_1.id, | ||
title="Sub Page 3 created from markdown file", | ||
markdown=markdown_file_path, | ||
).store() | ||
|
||
# Download the markdown file | ||
# delete the markdown file after downloading | ||
os.remove(markdown_file_path) | ||
markdown_file_2 = WikiPage( | ||
owner_id=my_test_project.id, id=markdown_wiki_2.id | ||
).get_markdown(download_file=True, download_location=".") | ||
|
||
print(f"Markdown file downloaded to: {markdown_file_2}") | ||
|
||
# Section 3: WikiPage with Attachments | ||
# Create a temporary file for the attachment | ||
attachment_file_name = "temp_attachment.txt.gz" | ||
with gzip.open(attachment_file_name, "wt", encoding="utf-8") as gz: | ||
gz.write("This is a sample attachment.") | ||
|
||
# reformat the attachment file name to be a valid attachment path | ||
attachment_file_name_reformatted = attachment_file_name.replace(".", "%2E") | ||
attachment_file_name_reformatted = attachment_file_name_reformatted.replace("_", "%5F") | ||
|
||
wiki_with_attachments = WikiPage( | ||
owner_id=my_test_project.id, | ||
parent_id=wiki_page_1.id, | ||
title="Sub Page 4 with Attachments", | ||
markdown=f"# Sub Page 4 with Attachments\n\nThis is a attachment: ${{previewattachment?fileName={attachment_file_name_reformatted}}}", | ||
attachments=[attachment_file_name], | ||
).store() | ||
|
||
# Get attachment handles | ||
attachment_handles = WikiPage( | ||
owner_id=my_test_project.id, id=wiki_with_attachments.id | ||
).get_attachment_handles() | ||
print(f"Found {len(attachment_handles['list'])} attachments") | ||
|
||
# Delete the attachment file after uploading --> check if the file is deleted | ||
os.remove(attachment_file_name) | ||
# Download an attachment | ||
wiki_page = WikiPage( | ||
owner_id=my_test_project.id, id=wiki_with_attachments.id | ||
).get_attachment( | ||
file_name=attachment_file_name, | ||
download_file=True, | ||
download_location=".", | ||
) | ||
print(f"Attachment downloaded: {os.path.exists(attachment_file_name)}") | ||
|
||
# Get attachment URL without downloading | ||
wiki_page_url = WikiPage( | ||
owner_id=my_test_project.id, id=wiki_with_attachments.id | ||
).get_attachment( | ||
file_name="temp_attachment.txt.gz", | ||
download_file=False, | ||
) | ||
print(f"Attachment URL: {wiki_page_url}") | ||
|
||
# Download an attachment preview--? Failed to download the attachment preview, synapseclient.core.exceptions.SynapseHTTPError: 404 Client Error: Cannot find a wiki attachment for OwnerID: syn68493645, ObjectType: ENTITY, WikiPageId: 633100, fileName: preview.txt | ||
attachment_handles = WikiPage( | ||
owner_id=my_test_project.id, id=wiki_with_attachments.id | ||
).get_attachment_handles() | ||
print(f"Attachment handles: {attachment_handles}") | ||
wiki_page = WikiPage( | ||
owner_id=my_test_project.id, id=wiki_with_attachments.id | ||
).get_attachment_preview( | ||
file_name="preview.txt", | ||
download_file=True, | ||
download_location=".", | ||
) | ||
|
||
# Section 4: WikiHeader - Working with Wiki Hierarchy | ||
|
||
# Get wiki header tree (hierarchy) | ||
# Note: Uncomment to actually get the header tree | ||
headers = WikiHeader.get(owner_id=my_test_project.id) | ||
print(f"Found {len(headers)} wiki pages in hierarchy") | ||
|
||
# Section 5. WikiHistorySnapshot - Version History | ||
# Get wiki history | ||
history = WikiHistorySnapshot.get(owner_id=my_test_project.id, id=wiki_page_1.id) | ||
|
||
print(f"Found {len(history)} versions in history for {wiki_page_1.title}") | ||
|
||
# Section 6. WikiOrderHint - Ordering Wiki Pages | ||
# Get wiki order hint --> failed to get the order hint | ||
order_hint = WikiOrderHint(owner_id=my_test_project.id).get() | ||
print(f"Order hint for {my_test_project.id}: {order_hint}") | ||
|
||
# Update wiki order hint | ||
order_hint.id_list = [wiki_page_1.id] | ||
|
||
print(f"Created order hint for {len(order_hint.id_list)} wiki pages") | ||
|
||
# Update order hint | ||
order_hint.id_list = ["633084", "633085", "633086", "633087", "633088"] # Reorder | ||
order_hint.store() | ||
|
||
# Delete a wiki page | ||
wiki_page_to_delete = WikiPage( | ||
owner_id=my_test_project.id, id=wiki_with_attachments.id | ||
).delete() | ||
|
||
# clean up | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would leave the project delete call out of the tutorial. For the wiki page that is being deleted, I might consider making a new wiki page specifically to delete, rather than delete one of the ones used earlier in the tutorial |
||
my_test_project.delete() |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fantastic tutorial! |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,152 @@ | ||
# Wikis on Projects | ||
 | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that this tutorial exists it will need to be added to the page navigation in the mkdocs.yml file |
||
# Synapse Wiki Models Tutorial | ||
|
||
This tutorial demonstrates how to work with Wiki models in the Synapse Python client. Wikis in Synapse provide a way to create rich documentation and collaborative content for projects, folders, files, datasets, and other entities. | ||
|
||
## Overview | ||
|
||
The Synapse Wiki models include: | ||
- **WikiPage**: The main wiki page model for creating and managing wiki content | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could these also hyperlink to the relevant api doc pages for each model? |
||
- **WikiHeader**: Represents wiki page headers and hierarchy information | ||
- **WikiHistorySnapshot**: Provides access to wiki version history | ||
- **WikiOrderHint**: Manages the order of wiki pages within an entity | ||
|
||
This tutorial shows how to: | ||
1. Create, read, and update wiki pages | ||
2. Work with WikiPage Markdown | ||
3. Work with WikiPage Attachments | ||
4. Work with WikiHeader | ||
5. Work with WikiHistorySnapshot | ||
6. Work with WikiOrderHint | ||
7. Delete wiki pages | ||
|
||
## Basic Setup | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=14-29} | ||
``` | ||
|
||
## 1. Create, read, and update wiki pages | ||
### Create a new wiki page for the project with plain text markdown | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=33-37} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Iine 32 is missing, that is where the project variable is created |
||
``` | ||
|
||
### OR you can create a wiki page with an existing markdown file | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=40-45} | ||
``` | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A great addition would be to include a section that can be expanded to show what the console logs would be after running a particular step. There are some examples on other tutorials that can be followed |
||
### Create a new wiki page with updated content | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=48-53} | ||
``` | ||
|
||
### Restore the wiki page to the original version | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=56-64} | ||
``` | ||
|
||
### Create a sub-wiki page | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=67-72} | ||
``` | ||
|
||
### Get an existing wiki page for the project, now you can see one root wiki page and one sub-wiki page | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=75-76} | ||
``` | ||
|
||
### Retrieving a Wiki Page | ||
Note: You need to know the wiki page ID or wiki page title to retrieve it | ||
#### Retrieve a Wiki Page with wiki page ID | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=79-80} | ||
``` | ||
|
||
#### Retrieve a Wiki Page with wiki page title | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=83-84} | ||
``` | ||
|
||
#### Check if the retrieved wiki page is the same as the original wiki page | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=87-92} | ||
``` | ||
|
||
## 2. WikiPage Markdown Operations | ||
### Create wiki page from markdown text | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=96-119} | ||
``` | ||
|
||
### Create wiki page from a markdown file | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=123-133} | ||
``` | ||
|
||
### Download the markdown file | ||
Note: If the markdown is generated from plain text using the client, the downloaded file will be named wiki_markdown_<wiki_page_id>.md.gz. If it is generated from an existing markdown file, the downloaded file will retain the original filename with the .gz suffix appended. | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=137-143} | ||
``` | ||
|
||
## 3. WikiPage Attachments Operations | ||
### Create a wiki page with attachments | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=147-161} | ||
``` | ||
### Get the file handles of all attachments on this wiki page. | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=164-165} | ||
``` | ||
### Download an attachment | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=167-175} | ||
``` | ||
|
||
### Get attachment URL without downloading | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=178-182} | ||
``` | ||
|
||
### Download an attachment preview (WIP) | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=185-191} | ||
``` | ||
#### Get attachment preview URL without downloading (WIP) | ||
|
||
|
||
## 4. WikiHeader - Working with Wiki Hierarchy | ||
### Getting Wiki Header Tree | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=197-200} | ||
``` | ||
|
||
## 5. WikiHistorySnapshot - Version History | ||
|
||
### Accessing Wiki History | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=204-208} | ||
``` | ||
|
||
## 6. WikiOrderHint - Managing Wiki Order | ||
### Get wiki order hint (No id_list returned, same result getting from direct endpoint calls) | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=212-213} | ||
``` | ||
### Update wiki order hint | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=216-222} | ||
``` | ||
|
||
### Deleting a Wiki Page | ||
Note: You need to know the owner ID and wiki page ID to delete a wiki page | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=225} | ||
``` | ||
|
||
## clean up | ||
```python | ||
{!docs/tutorials/python/tutorial_scripts/wiki.py!lines=228} | ||
``` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There should be a final references section that links to all the functions and models used in the tutorial |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there another descriptive way we can word some of these actions rather than "Work with.." maybe, describing the create/update/delete/restore actions taking place during that section of code?