Skip to content

Commit 210bf36

Browse files
authored
[SYNPY-1671] Adding store & delete factory method, find_entity_id, is_synapse_id, onweb, md5_query (#1300)
* Adding delete factory method * [SYNPY-1674] Creating functions for additional Synapse class methods, find_entity_id, is_synapse_id, onweb, md5_query (#1301)
1 parent 2b44e52 commit 210bf36

24 files changed

Lines changed: 6973 additions & 15 deletions

docs/explanations/structuring_your_project.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,6 @@ Manifests are crucial for the organization of your data in Synapse. In the **hie
108108

109109
### An example: ELITE portal
110110

111-
Synapse Project: https://www.synapse.org/#!Synapse:syn27229419/wiki/623145
111+
Synapse Project: https://www.synapse.org/Synapse:syn27229419/wiki/623145
112112

113113
This project powers the elite portal: https://eliteportal.synapse.org/. More information about the studies and the files can be found in this portal.

docs/reference/experimental/async/factory_operations.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,49 @@ at your own risk.
2828
::: synapseclient.operations.LinkOptions
2929
options:
3030
inherited_members: true
31+
32+
[](){ #factory-delete-async }
33+
::: synapseclient.operations.delete_async
34+
35+
[](){ #factory-store-async }
36+
::: synapseclient.operations.store_async
37+
38+
[](){ #factory-store-file-options-async }
39+
::: synapseclient.operations.StoreFileOptions
40+
options:
41+
inherited_members: true
42+
43+
[](){ #factory-store-container-options-async }
44+
::: synapseclient.operations.StoreContainerOptions
45+
options:
46+
inherited_members: true
47+
48+
[](){ #factory-store-table-options-async }
49+
::: synapseclient.operations.StoreTableOptions
50+
options:
51+
inherited_members: true
52+
53+
[](){ #factory-store-json-schema-options-async }
54+
::: synapseclient.operations.StoreJSONSchemaOptions
55+
options:
56+
inherited_members: true
57+
58+
[](){ #factory-store-grid-options-async }
59+
::: synapseclient.operations.StoreGridOptions
60+
options:
61+
inherited_members: true
62+
63+
[](){ #factory-find-entity-id-async }
64+
::: synapseclient.operations.find_entity_id_async
65+
66+
[](){ #factory-is-synapse-id-async }
67+
::: synapseclient.operations.is_synapse_id_async
68+
69+
[](){ #factory-onweb-async }
70+
::: synapseclient.operations.onweb_async
71+
72+
[](){ #factory-md5-query-async }
73+
::: synapseclient.operations.md5_query_async
74+
75+
[](){ #factory-print-entity-async }
76+
::: synapseclient.operations.print_entity_async

docs/reference/experimental/sync/factory_operations.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,49 @@ at your own risk.
2828
::: synapseclient.operations.LinkOptions
2929
options:
3030
inherited_members: true
31+
32+
[](){ #factory-delete-sync }
33+
::: synapseclient.operations.delete
34+
35+
[](){ #factory-store-sync }
36+
::: synapseclient.operations.store
37+
38+
[](){ #factory-store-file-options-sync }
39+
::: synapseclient.operations.StoreFileOptions
40+
options:
41+
inherited_members: true
42+
43+
[](){ #factory-store-container-options-sync }
44+
::: synapseclient.operations.StoreContainerOptions
45+
options:
46+
inherited_members: true
47+
48+
[](){ #factory-store-table-options-sync }
49+
::: synapseclient.operations.StoreTableOptions
50+
options:
51+
inherited_members: true
52+
53+
[](){ #factory-store-json-schema-options-sync }
54+
::: synapseclient.operations.StoreJSONSchemaOptions
55+
options:
56+
inherited_members: true
57+
58+
[](){ #factory-store-grid-options-sync }
59+
::: synapseclient.operations.StoreGridOptions
60+
options:
61+
inherited_members: true
62+
63+
[](){ #factory-find-entity-id-sync }
64+
::: synapseclient.operations.find_entity_id
65+
66+
[](){ #factory-is-synapse-id-sync }
67+
::: synapseclient.operations.is_synapse_id
68+
69+
[](){ #factory-onweb-sync }
70+
::: synapseclient.operations.onweb
71+
72+
[](){ #factory-md5-query-sync }
73+
::: synapseclient.operations.md5_query
74+
75+
[](){ #factory-print-entity-sync }
76+
::: synapseclient.operations.print_entity

docs/tutorials/home.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ organizing, and discussing your scientific research.
77

88
## What do you need to get started?
99
First off, to browse Synapse and access its most basic level of functionality, you
10-
will need to [register for a Synapse account](https://www.synapse.org/#!RegisterAccount:0).
10+
will need to [register for a Synapse account](https://www.synapse.org/RegisterAccount:0).
1111
In doing so, you will be agreeing to the
1212
[Synapse Code of Conduct and Synapse Terms and Conditions of Use](https://help.synapse.org/docs/Synapse-Governance.2004255211.html).
1313

@@ -38,7 +38,7 @@ conditions for use.
3838

3939
To work with data of your own or your team’s, you must become a
4040
[certified user](https://help.synapse.org/docs/Synapse-User-Account-Types.2007072795.html#SynapseUserAccountTypes-CertifiedUser). To become certified, you must pass a
41-
[certification quiz](https://www.synapse.org/#!Quiz:Certification),
41+
[certification quiz](https://www.synapse.org/Quiz:Certification),
4242
which will ask you about information that can be found throughout this documentation site.
4343

4444

docs/tutorials/python/project.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ project = Project(name="My uniquely named project about Alzheimer's Disease")
3030
project.store()
3131
```
3232

33-
Now that you have created your project you are able to inspect the project in the [synapse web UI](https://www.synapse.org/#!Profile:v/projects/created_by_me).
33+
Now that you have created your project you are able to inspect the project in the [synapse web UI](https://www.synapse.org/Profile:v/projects/created_by_me).
3434

3535

3636

synapseclient/api/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
get_entity_type,
5656
get_upload_destination,
5757
get_upload_destination_location,
58+
is_synapse_id,
5859
post_entity,
5960
post_entity_acl,
6061
put_entity,
@@ -162,6 +163,7 @@
162163
get_user_profile_by_username,
163164
is_user_certified,
164165
)
166+
from .web_services import open_entity_in_browser
165167
from .wiki_services import (
166168
delete_wiki_page,
167169
get_attachment_handles,
@@ -229,6 +231,9 @@
229231
"put_entity_acl",
230232
"set_entity_permissions",
231233
"update_entity_acl",
234+
"is_synapse_id",
235+
# web_services
236+
"open_entity_in_browser",
232237
# configuration_services
233238
"get_config_file",
234239
"get_config_section_dict",

synapseclient/api/entity_services.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,3 +1656,73 @@ async def main():
16561656
else:
16571657
# Entity inherits from a benefactor, use POST to create new ACL
16581658
return await client.rest_post_async(uri=uri, body=json.dumps(acl))
1659+
1660+
1661+
async def is_synapse_id(
1662+
syn_id: str,
1663+
*,
1664+
synapse_client: Optional["Synapse"] = None,
1665+
) -> bool:
1666+
"""
1667+
Check if given synID is valid (attached to actual entity).
1668+
1669+
Arguments:
1670+
syn_id: A Synapse ID to validate.
1671+
synapse_client: If not passed in and caching was not disabled by
1672+
`Synapse.allow_client_caching(False)` this will use the last created
1673+
instance from the Synapse class constructor.
1674+
1675+
Returns:
1676+
True if the Synapse ID is valid and exists.
1677+
1678+
Example: Validating a Synapse ID
1679+
Check if a Synapse ID exists:
1680+
1681+
```python
1682+
import asyncio
1683+
from synapseclient import Synapse
1684+
from synapseclient.api import is_synapse_id
1685+
1686+
syn = Synapse()
1687+
syn.login()
1688+
1689+
async def main():
1690+
if await is_synapse_id("syn123456"):
1691+
print("Valid Synapse ID")
1692+
else:
1693+
print("Invalid or non-existent Synapse ID")
1694+
1695+
asyncio.run(main())
1696+
```
1697+
"""
1698+
from synapseclient.core.exceptions import (
1699+
SynapseAuthenticationError,
1700+
SynapseFileNotFoundError,
1701+
)
1702+
1703+
if not isinstance(syn_id, str):
1704+
return False
1705+
1706+
try:
1707+
await get_entity(entity_id=syn_id, synapse_client=synapse_client)
1708+
except SynapseFileNotFoundError:
1709+
return False
1710+
except (SynapseHTTPError, SynapseAuthenticationError) as err:
1711+
# Extract status code
1712+
status = None
1713+
if hasattr(err, "__context__") and hasattr(err.__context__, "response"):
1714+
status = err.__context__.response.status_code
1715+
elif hasattr(err, "response"):
1716+
status = err.response.status_code
1717+
1718+
# If we can't determine the status, re-raise the exception
1719+
if status is None:
1720+
raise
1721+
1722+
if status in (400, 404):
1723+
return False
1724+
# Valid ID but user lacks permission or is not logged in
1725+
elif status == 403:
1726+
return True
1727+
raise
1728+
return True

synapseclient/api/web_services.py

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
"""This module provides web browser-related services for Synapse entities."""
2+
3+
import webbrowser
4+
from typing import TYPE_CHECKING, Optional, Union
5+
6+
from synapseclient.core.utils import id_of
7+
8+
if TYPE_CHECKING:
9+
from synapseclient import Synapse
10+
from synapseclient.models import (
11+
Dataset,
12+
DatasetCollection,
13+
EntityView,
14+
File,
15+
Folder,
16+
Link,
17+
MaterializedView,
18+
Project,
19+
RecordSet,
20+
SubmissionView,
21+
Table,
22+
VirtualTable,
23+
)
24+
25+
26+
async def open_entity_in_browser(
27+
entity: Union[
28+
str,
29+
"Dataset",
30+
"DatasetCollection",
31+
"EntityView",
32+
"File",
33+
"Folder",
34+
"Link",
35+
"MaterializedView",
36+
"Project",
37+
"RecordSet",
38+
"SubmissionView",
39+
"Table",
40+
"VirtualTable",
41+
],
42+
subpage_id: Optional[str] = None,
43+
*,
44+
synapse_client: Optional["Synapse"] = None,
45+
) -> str:
46+
"""
47+
Open up a browser window to the entity page or wiki-subpage.
48+
49+
Arguments:
50+
entity: Either an Entity object (Dataset, DatasetCollection, EntityView,
51+
File, Folder, Link, MaterializedView, Project, RecordSet,
52+
SubmissionView, Table, VirtualTable) or a Synapse ID string.
53+
subpage_id: (Optional) ID of one of the wiki's sub-pages.
54+
synapse_client: If not passed in and caching was not disabled by
55+
`Synapse.allow_client_caching(False)` this will use the last created
56+
instance from the Synapse class constructor.
57+
58+
Returns:
59+
The URL that was opened in the browser.
60+
61+
Example: Opening an entity in browser
62+
Open an entity's page in the default web browser:
63+
64+
```python
65+
import asyncio
66+
from synapseclient import Synapse
67+
from synapseclient.api import open_entity_in_browser
68+
69+
syn = Synapse()
70+
syn.login()
71+
72+
async def main():
73+
url = await open_entity_in_browser("syn123456")
74+
print(f"Opened: {url}")
75+
76+
asyncio.run(main())
77+
```
78+
79+
Example: Opening a wiki subpage
80+
Open a specific wiki subpage:
81+
82+
```python
83+
import asyncio
84+
from synapseclient import Synapse
85+
from synapseclient.api import open_entity_in_browser
86+
87+
syn = Synapse()
88+
syn.login()
89+
90+
async def main():
91+
url = await open_entity_in_browser("syn123456", subpage_id="12345")
92+
print(f"Opened wiki subpage: {url}")
93+
94+
asyncio.run(main())
95+
```
96+
"""
97+
from synapseclient import Synapse
98+
99+
client = Synapse.get_client(synapse_client=synapse_client)
100+
101+
synapse_id = id_of(entity)
102+
103+
# Construct the URL
104+
portal_endpoint = client.portalEndpoint
105+
if subpage_id is None:
106+
url = f"{portal_endpoint}/Synapse:{synapse_id}"
107+
else:
108+
url = f"{portal_endpoint}/Wiki:{synapse_id}/ENTITY/{subpage_id}"
109+
110+
# Open in browser
111+
webbrowser.open(url)
112+
113+
return url

0 commit comments

Comments
 (0)