diff --git a/docs/news.md b/docs/news.md index a3b5cb48a..a443abb2e 100644 --- a/docs/news.md +++ b/docs/news.md @@ -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 diff --git a/docs/tutorials/python/json_schema.md b/docs/tutorials/python/json_schema.md index fd07b8efb..ba9151a6a 100644 --- a/docs/tutorials/python/json_schema.md +++ b/docs/tutorials/python/json_schema.md @@ -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). @@ -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 @@ -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} ```
@@ -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} ```
@@ -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} ``` @@ -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} ``` @@ -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} ```
diff --git a/docs/tutorials/python/tutorial_scripts/json_schema.py b/docs/tutorials/python/tutorial_scripts/json_schema.py index 786e6a3f3..501295754 100644 --- a/docs/tutorials/python/tutorial_scripts/json_schema.py +++ b/docs/tutorials/python/tutorial_scripts/json_schema.py @@ -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( @@ -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" @@ -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) @@ -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: @@ -101,15 +100,15 @@ # 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 @@ -117,53 +116,31 @@ "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)) diff --git a/synapseclient/synapsePythonClient b/synapseclient/synapsePythonClient index 5aeb673c5..7ada7c506 100644 --- a/synapseclient/synapsePythonClient +++ b/synapseclient/synapsePythonClient @@ -1,6 +1,6 @@ { "client": "synapsePythonClient", - "latestVersion": "4.7.0", + "latestVersion": "4.9.0", "blacklist": [ "0.0.0", "0.4.1",