Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions docs/news.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,99 @@ detailing some of the changes.
the 4.x.x versions hidden behind optional feature flags or different import paths. Any
breaking changes will not be included until v5.0.

## 4.9.0 (2025-07-09)

## Highlights

- Multi-Profile support is now available when using the `.synapseConfig` file. Check out the [updated Authentication instructions](https://python-docs.synapse.org/en/latest/tutorials/authentication/#use-synapseconfig) that covers how to take advantage of this feature.
- Introduced streamlined functionality for [managing JSON schemas](https://python-docs.synapse.org/en/latest/tutorials/python/json_schema/) and [access control lists](https://python-docs.synapse.org/en/latest/tutorials/python/sharing_settings/) (ACLs)
- Enhanced OpenTelemetry tracing for file transfers and MD5 calculations
- Added support for [Virtual Tables](https://python-docs.synapse.org/en/latest/tutorials/python/virtualtable/)

## Features

- [SYNPY-893] Added support for multiple authentication profiles ([#1194](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1194))
- [SYNPY-1580] Implemented `VirtualTable` OOP model ([#1195](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1195))
- [SYNPY-1599] Added JSON schema mixin class for binding, validating, and unbinding schemas ([#1205](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1205))
- [SYNPY-1607] Enabled string-based conversion for `ColumnType` and `FacetType` ([#1210](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1210))
- [SYNPY-1604] Introduced `dry_run` flag and `list_acl` method for ACL management ([#1207](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1207))
- [SYNPY-1244] Implemented recursive ACL deletion and permission inheritance detection ([#1200](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1200), [#1202](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1202))

## Bug Fixes

- [SYNPY-1581] Removed exception logging and raising in async methods ([#1203](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1203))

## Tech Debt

- [SYNPY-1295] Trimmed down integration tests and combined similar logic ([#1199](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1199))
- [SYNPY-1606] Added OpenTelemetry metrics for file uploads, downloads, and MD5 calculations ([#1204](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1204))
- [SYNPY-1618] Added scripts for cleaning up test resources in Synapse ([#1209](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1209))
- [SYNPY-1599] Patched JSON schema code and improved examples ([#1211](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1211))

## New Contributors
* @SageGJ made their first contribution in https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1203
* @carmmmm made their first contribution in https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1183

Full Changelog: https://github.com/Sage-Bionetworks/synapsePythonClient/compare/v4.8.0...v4.9.0-rc

## 4.8.0 (2025-04-28)

### Highlights

- Introduced new object-oriented models for working with Synapse [Datasets](https://python-docs.synapse.org/en/stable/tutorials/python/dataset/), [DatasetCollections](https://python-docs.synapse.org/en/stable/tutorials/python/dataset_collection/), [EntityViews](https://python-docs.synapse.org/en/stable/tutorials/python/entityview/), [MaterializedViews](https://python-docs.synapse.org/en/stable/tutorials/python/materializedview/), and [SubmissionViews](https://python-docs.synapse.org/en/stable/tutorials/python/submissionview/). This includes tutorials for each of these models.
- Improved handling of progress bars, logging, and error messages
- Added support for Python 3.13

### Features

- [SYNPY-1571] Introduced `Dataset` model and composition model for `Table`/`View`-like classes ([#1175](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1175))
- [SYNPY-1575] Introduced `EntityView` model ([#1181](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1181))
- [SYNPY-1579] Introduced `MaterializedView` model ([#1190](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1190))
- [SYNPY-1577] Introduced `SubmissionView` model ([#1192](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1192))
- [SYNPY-1578] Introduced `DatasetCollection` model ([#1189](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1189))

### Bug Fixes

- [SYNPY-1593] Enforce minimum httpcore dependency to prevent critical CVE ([#1197](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1197))
- [SYNPY-1547] Fixed `parentWikiId=""` bug ([#1165](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1165))
- [SYNPY-1553] Removed blank auth header and improved error message for unauthenticated requests ([#1171](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1171), [#1185](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1185))
- [SYNPY-1584] Fixed issue with DataFrame upload and header writing ([#1193](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1193))

### Tech Debt

- [SYNPY-1551] Refactored `Table` model ([#1151](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1151))
- [SYNPY-1488] Patched nested TQDM progress bars and messages to logger ([#1177](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1177))
- [SYNPY-1497] Refactored version check to use PyPI for version info ([#1191](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1191))

### Other

- [DPE-1253] Added PR template for GitHub Pull requests ([#1182](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1182))
- [SYNPY-1542] Upgraded ReadTheDocs OS, Python version, and search ranking ([#1184](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1184))
- Updated Dockerfile to fix `pandas` installation ([#1169](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1169))
- Updated table and file versioning tutorials ([#1172](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1172))
- Prevented concurrent builds per branch ([#1178](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1178))
- Included default timeout for HTTP requests ([#1188](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1188))
- Corrected regular expression for invalid column name ([#1187](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1187))
- Updated docstring for `setPermissions` function ([#1164](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1164))
- Added SECURITY.md ([#1166](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1166))
- Fixed typo in dataset tutorial ([#1186](https://github.com/Sage-Bionetworks/synapsePythonClient/pull/1186))


## 4.7.0 (2025-01-31)

### Highlights
- **Added functionality for interacting with Synapse Agents:**
- The new `Agent` OOP model allows you to chat with the baseline Synapse Agent,
register and chat with custom Synapse Agents, manage multiple chat sessions and more.
- See the `Agent` documentation for more details and example code to get started.

### Bug Fixes
- \[[SYNPY-1557](https://sagebionetworks.jira.com/browse/SYNPY-1557)\] - Synapse get recursive link download issue

### Stories
- \[[SYNPY-1544](https://sagebionetworks.jira.com/browse/SYNPY-1544)\] - Create Synapse Agent OOP Model
- \[[SYNPY-1566](https://sagebionetworks.jira.com/browse/SYNPY-1566)\] - Release python client v4.7.0

## 4.7.0 (2025-01-31)

### Highlights
Expand Down
20 changes: 10 additions & 10 deletions docs/tutorials/python/json_schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ By the end of this tutorial, you will:
## 2. Take a Look at the Constants and Structure of the JSON Schema

```python
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=22-49}
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=21-49}
```

Derived annotations allow you to define default values for annotations based on schema rules, ensuring consistency and reducing manual input errors. As you can see here, you could use derived annotations to prescribe default annotation values. Please read more about derived annotations [here](https://help.synapse.org/docs/JSON-Schemas.3107291536.html#JSONSchemas-DerivedAnnotations).
Expand All @@ -39,12 +39,12 @@ Derived annotations allow you to define default values for annotations based on
## 3. Try Create Test Organization and JSON Schema if They Do Not Exist
Next, try creating a test organization and register a schema if they do not already exist:
```python
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=52-65}
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=51-65}
```

Note: If you update your schema, you can re-register it with the organization by assigning a new version number to reflect the changes. Synapse does not allow re-creating a schema with the same version number, so please ensure that each schema version within an organization is unique:
```python
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=68-99}
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=67-99}
```

## 4. Bind the JSON Schema to the Folder
Expand All @@ -53,7 +53,7 @@ After creating the organization, you can now bind your json schema to a test fol
When you bind the schema, you may also include the boolean property `enable_derived_annotations` to have Synapse automatically calculate derived annotations based on the schema:

```python
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=102-108}
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=101-108}
```

<details class="example">
Expand All @@ -76,7 +76,7 @@ JSON schema was bound successfully. Please see details below:
## 5. Retrieve the Bound Schema
Next, we can retrieve the bound schema:
```python
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=111-113}
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=110-113}
```

<details class="example">
Expand Down Expand Up @@ -105,12 +105,12 @@ JSON Schema was retrieved successfully. Please see details below:
## 6. Add Invalid Annotations to the Folder and Store, and Validate the Folder against the Schema
Try adding invalid annotations to your folder: This step and the step below demonstrate how the system handles invalid annotations and how the schema validation process works.
```python
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=116-120}
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=115-119}
```

Try validating the folder. You should be able to see messages related to invalid annotations.
```python
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=124-126}
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=123-125}
```


Expand Down Expand Up @@ -146,12 +146,12 @@ This step is only relevant for container entities, such as a folder or a project

Try creating a test file locally and store the file in the folder that we created earlier. Then, try adding invalid annotations to that file. This step demonstrates how the files inside a folder also inherit the schema from the parent entity.
```python
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=130-155}
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=129-134}
```

You could then use `get_schema_validation_statistics` to get information such as the number of children with invalid annotations inside a container.
```python
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=158-160}
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=137-141}
```


Expand All @@ -170,7 +170,7 @@ Validation statistics were retrieved successfully. Please see details below:

You could also use `get_invalid_validation` to see more detailed results of all the children inside a container, which includes all validation messages and validation exception details.
```python
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=162-169}
{!docs/tutorials/python/tutorial_scripts/json_schema.py!lines=143-146}
```

<details class="example">
Expand Down
55 changes: 16 additions & 39 deletions docs/tutorials/python/tutorial_scripts/json_schema.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import os
import time
from pprint import pprint

import synapseclient
from synapseclient.core.utils import make_bogus_data_file
from synapseclient.models import File, Folder

# 1. Set up Synapse Python client and retrieve project
syn = synapseclient.Synapse()
syn.login()
client = synapseclient.Synapse().get_client(synapse_client=syn)

# Retrieve test project
PROJECT_ID = syn.findEntityId(
Expand All @@ -19,7 +18,7 @@
test_folder = Folder(name="clinical_data_folder", parent_id=PROJECT_ID).store()

# 2. Take a look at the constants and structure of the JSON schema
ORG_NAME = "myUniqueAlzheimersResearchOrgTurtorial"
ORG_NAME = "myUniqueAlzheimersResearchOrgTutorial"
VERSION = "0.0.1"
NEW_VERSION = "0.0.2"

Expand Down Expand Up @@ -53,10 +52,10 @@
all_orgs = js.list_organizations()
for org in all_orgs:
if org["name"] == ORG_NAME:
client.logger.info(f"Organization {ORG_NAME} already exists.")
syn.logger.info(f"Organization {ORG_NAME} already exists.")
break
else:
client.logger.info(f"Creating organization {ORG_NAME}.")
syn.logger.info(f"Creating organization {ORG_NAME}.")
js.create_organization(ORG_NAME)

my_test_org = js.JsonSchemaOrganization(ORG_NAME)
Expand Down Expand Up @@ -92,7 +91,7 @@
)
except synapseclient.core.exceptions.SynapseHTTPError as e:
if e.response.status_code == 400 and "already exists" in e.response.text:
client.logger.warning(
syn.logger.warning(
f"Schema {SCHEMA_NAME} already exists. Please switch to use a new version number."
)
else:
Expand All @@ -101,69 +100,47 @@
# 4. Bind the JSON schema to the folder
schema_uri = ORG_NAME + "-" + SCHEMA_NAME + "-" + VERSION
bound_schema = test_folder.bind_schema(
json_schema_uri=schema_uri, synapse_client=syn, enable_derived_annotations=True
json_schema_uri=schema_uri, enable_derived_annotations=True
)
json_schema_version_info = bound_schema.json_schema_version_info
client.logger.info("JSON schema was bound successfully. Please see details below:")
syn.logger.info("JSON schema was bound successfully. Please see details below:")
pprint(vars(json_schema_version_info))

# 5. Retrieve the Bound Schema
schema = test_folder.get_schema()
client.logger.info("JSON Schema was retrieved successfully. Please see details below:")
syn.logger.info("JSON Schema was retrieved successfully. Please see details below:")
pprint(vars(schema))

# 6. Add Invalid Annotations to the Folder and Store
test_folder.annotations = {
"patient_id": "1234",
"cognitive_score": "invalid str",
}
test_folder.store(synapse_client=syn)
test_folder.store()

time.sleep(2)

validation_results = test_folder.validate_schema()
client.logger.info("Validation was completed. Please see details below:")
syn.logger.info("Validation was completed. Please see details below:")
pprint(vars(validation_results))

# 7. Create a File with Invalid Annotations and Upload It
# Then, view validation statistics and invalid validation results
if not os.path.exists(os.path.expanduser("~/temp")):
os.makedirs(os.path.expanduser("~/temp/testJSONSchemaFiles"), exist_ok=True)

name_of_file = "test_file.txt"
path_to_file = os.path.join(
os.path.expanduser("~/temp/testJSONSchemaFiles"), name_of_file
)


def create_random_file(
path: str,
) -> None:
"""Create a random file with random data.

:param path: The path to create the file at.
"""
with open(path, "wb") as f:
f.write(os.urandom(1))


create_random_file(path_to_file)
path_to_file = make_bogus_data_file(n=5)

annotations = {"patient_id": "123456", "cognitive_score": "invalid child str"}

child_file = File(path=path_to_file, parent_id=test_folder.id, annotations=annotations)
child_file = child_file.store(synapse_client=syn)
child_file = child_file.store()
time.sleep(2)

validation_statistics = test_folder.get_schema_validation_statistics(synapse_client=syn)
client.logger.info(
validation_statistics = test_folder.get_schema_validation_statistics()
syn.logger.info(
"Validation statistics were retrieved successfully. Please see details below:"
)
pprint(vars(validation_statistics))

invalid_validation = invalid_results = test_folder.get_invalid_validation(
synapse_client=syn
)
invalid_validation = invalid_results = test_folder.get_invalid_validation()
for child in invalid_validation:
client.logger.info("See details of validation results: ")
syn.logger.info("See details of validation results: ")
pprint(vars(child))
2 changes: 1 addition & 1 deletion synapseclient/synapsePythonClient
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"client": "synapsePythonClient",
"latestVersion": "4.7.0",
"latestVersion": "4.9.0",
"blacklist": [
"0.0.0",
"0.4.1",
Expand Down
Loading