Skip to content

Folder

Contained within this file are experimental interfaces for working with the Synapse Python Client. Unless otherwise noted these interfaces are subject to change at any time. Use at your own risk.

Example Script

Working with folders
"""
Expects that ~/temp exists and is a directory.

The purpose of this script is to demonstrate how to use the new OOP interface for folders.
The following actions are shown in this script:
1. Creating a folder
2. Storing a folder to a project
3. Storing several files to a folder
4. Storing several folders in a folder
5. Getting metadata about a folder and it's immediate children
6. Updating the annotations in bulk for a number of folders and files
7. Deleting a folder
8. Copying a folder
9. Moving a folder
10. Using sync_from_synapse to download the files and folders
"""

import os
from datetime import date, datetime, timedelta, timezone

import synapseclient
from synapseclient.models import File, Folder

PROJECT_ID = "syn52948289"

syn = synapseclient.Synapse(debug=True)
syn.login()


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))


def try_delete_folder(folder_name: str, parent_id: str) -> None:
    """Simple try catch to delete a folder."""
    try:
        Folder(name=folder_name, parent_id=parent_id).get().delete()
    except Exception:
        pass


def store_folder():
    # Clean up synapse for previous runs:
    try_delete_folder("my_new_folder_for_this_project", PROJECT_ID)
    try_delete_folder("destination_for_copy", PROJECT_ID)
    try_delete_folder("my_new_folder_for_this_project_I_want_to_delete", PROJECT_ID)

    # Creating annotations for my folder ==================================================
    annotations_for_my_folder = {
        "my_single_key_string": "a",
        "my_key_string": ["b", "a", "c"],
        "my_key_bool": [False, False, False],
        "my_key_double": [1.2, 3.4, 5.6],
        "my_key_long": [1, 2, 3],
        "my_key_date": [date.today(), date.today() - timedelta(days=1)],
        "my_key_datetime": [
            datetime.today(),
            datetime.today() - timedelta(days=1),
            datetime.now(tz=timezone(timedelta(hours=-5))),
            datetime(2023, 12, 7, 13, 0, 0, tzinfo=timezone(timedelta(hours=0))),
            datetime(2023, 12, 7, 13, 0, 0, tzinfo=timezone(timedelta(hours=-7))),
        ],
    }

    # 1) Creating a folder ===============================================================
    root_folder_for_my_project = Folder(
        name="my_new_folder_for_this_project",
        annotations=annotations_for_my_folder,
        parent_id=PROJECT_ID,
        description="This is a folder with random data.",
    )

    root_folder_for_my_project = root_folder_for_my_project.store()

    print(
        f"Folder created: {root_folder_for_my_project.name} with id: {root_folder_for_my_project.id}"
    )

    # 2) Updating and storing an annotation ==============================================
    new_folder_instance = Folder(id=root_folder_for_my_project.id).get()
    new_folder_instance.annotations["my_key_string"] = ["new", "values", "here"]
    stored_folder = new_folder_instance.store()
    print(f"Folder {stored_folder.name} updated with new annotations:")
    print(stored_folder.annotations)

    # 3) Storing several files to a folder ===============================================
    files_to_store = []
    for loop in range(1, 10):
        name_of_file = f"my_file_with_random_data_{loop}.txt"
        path_to_file = os.path.join(os.path.expanduser("~/temp"), name_of_file)
        create_random_file(path_to_file)

        file = File(
            path=path_to_file,
            name=name_of_file,
        )
        files_to_store.append(file)
    root_folder_for_my_project.files = files_to_store
    root_folder_for_my_project = root_folder_for_my_project.store()

    # 4) Storing several folders in a folder =============================================
    folders_to_store = []
    for loop in range(1, 10):
        folder_to_store = Folder(
            name=f"my_new_folder_for_this_project_{loop}",
        )
        folders_to_store.append(folder_to_store)
    root_folder_for_my_project.folders = folders_to_store
    root_folder_for_my_project = root_folder_for_my_project.store()

    # 5) Getting metadata about a folder and it's immediate children =====================
    new_folder_instance = Folder(id=root_folder_for_my_project.id).sync_from_synapse(
        download_file=False, recursive=False
    )

    print(f"Synced folder {new_folder_instance.name} from synapse")
    for file in new_folder_instance.files:
        print(f"Found File in Synapse at: {new_folder_instance.name}/{file.name}")

    for folder in new_folder_instance.folders:
        print(f"Found Folder in Synapse at: {new_folder_instance.name}/{folder.name}")

    # 6) Updating the annotations in bulk for a number of folders and files ==============
    new_annotations = {
        "my_new_key_string": ["b", "a", "c"],
    }

    for file in new_folder_instance.files:
        file.annotations = new_annotations

    for folder in new_folder_instance.folders:
        folder.annotations = new_annotations

    new_folder_instance.store()

    # 7) Deleting a folder ===============================================================
    folder_to_delete = Folder(
        name="my_new_folder_for_this_project_I_want_to_delete",
        parent_id=PROJECT_ID,
    ).store()

    folder_to_delete.delete()

    # 8) Copying a folder ===============================================================
    destination_folder_to_copy_to = Folder(
        name="destination_for_copy", parent_id=PROJECT_ID
    ).store()
    coped_folder = root_folder_for_my_project.copy(
        parent_id=destination_folder_to_copy_to.id
    )

    print(
        f"Copied folder from {root_folder_for_my_project.id} to {coped_folder.id} in synapse"
    )

    # You'll also see all the files/folders were copied too
    for file in coped_folder.files:
        print(f"Found (copied) File in Synapse at: {coped_folder.name}/{file.name}")

    for folder in coped_folder.folders:
        print(f"Found (copied) Folder in Synapse at: {coped_folder.name}/{folder.name}")

    # 9) Moving a folder ===============================================================
    folder_i_am_going_to_move = Folder(
        name="folder_i_am_going_to_move", parent_id=PROJECT_ID
    ).store()
    current_parent_id = folder_i_am_going_to_move.parent_id
    folder_i_am_going_to_move.parent_id = destination_folder_to_copy_to.id
    folder_i_am_going_to_move.store()
    print(
        f"Moved folder from {current_parent_id} to {folder_i_am_going_to_move.parent_id}"
    )

    # 10) Using sync_from_synapse to download the files and folders ======================
    # This will download all the files and folders in the folder to the local file system
    path_to_download = os.path.expanduser("~/temp/recursiveDownload")
    if not os.path.exists(path_to_download):
        os.mkdir(path_to_download)
    root_folder_for_my_project.sync_from_synapse(path=path_to_download)


store_folder()

API Reference

synapseclient.models.Folder dataclass

Bases: FolderSynchronousProtocol, AccessControllable, StorableContainer, ContainerEntityJSONSchema

Folder is a hierarchical container for organizing data in Synapse.

ATTRIBUTE DESCRIPTION
id

The unique immutable ID for this folder. A new ID will be generated for new Folders. Once issued, this ID is guaranteed to never change or be re-issued.

TYPE: Optional[str]

name

The name of this folder. Must be 256 characters or less. Names may only contain: letters, numbers, spaces, underscores, hyphens, periods, plus signs, apostrophes, and parentheses.

TYPE: Optional[str]

parent_id

The ID of the Project or Folder that is the parent of this Folder.

TYPE: Optional[str]

description

The description of this entity. Must be 1000 characters or less.

TYPE: Optional[str]

etag

(Read Only) Synapse employs an Optimistic Concurrency Control (OCC) scheme to handle concurrent updates. Since the E-Tag changes every time an entity is updated it is used to detect when a client's current representation of an entity is out-of-date.

TYPE: Optional[str]

created_on

(Read Only) The date this entity was created.

TYPE: Optional[str]

modified_on

(Read Only) The date this entity was last modified.

TYPE: Optional[str]

created_by

(Read Only) The ID of the user that created this entity.

TYPE: Optional[str]

modified_by

(Read Only) The ID of the user that last modified this entity.

TYPE: Optional[str]

files

Files that exist within this folder.

TYPE: List[File]

folders

Folders that exist within this folder.

TYPE: List[Folder]

tables

Tables that exist within this folder.

TYPE: List[Table]

entityviews

Entity views that exist within this folder.

TYPE: List[EntityView]

submissionviews

Submission views that exist within this folder.

TYPE: List[SubmissionView]

datasets

Datasets that exist within this folder.

TYPE: List[Dataset]

datasetcollections

Dataset collections that exist within this folder.

TYPE: List[DatasetCollection]

materializedviews

Materialized views that exist within this folder.

TYPE: List[MaterializedView]

virtualtables

Virtual tables that exist within this folder.

TYPE: List[VirtualTable]

annotations

Additional metadata associated with the folder. The key is the name of your desired annotations. The value is an object containing a list of values (use empty list to represent no values for key) and the value type associated with all values in the list. To remove all annotations set this to an empty dict {} or None and store the entity.

TYPE: Optional[Dict[str, Union[List[str], List[bool], List[float], List[int], List[date], List[datetime]]]]

create_or_update

(Store only) Indicates whether the method should automatically perform an update if the resource conflicts with an existing Synapse object. When True this means that any changes to the resource will be non-destructive.

This boolean is ignored if you've already stored or retrieved the resource from Synapse for this instance at least once. Any changes to the resource will be destructive in this case. For example if you want to delete the content for a field you will need to call .get() and then modify the field.

TYPE: bool

Source code in synapseclient/models/folder.py
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
@dataclass()
@async_to_sync
class Folder(
    FolderSynchronousProtocol,
    AccessControllable,
    StorableContainer,
    ContainerEntityJSONSchema,
):
    """Folder is a hierarchical container for organizing data in Synapse.

    Attributes:
        id: The unique immutable ID for this folder. A new ID will be generated for new
            Folders. Once issued, this ID is guaranteed to never change or be re-issued.
        name: The name of this folder. Must be 256 characters or less. Names may only
            contain: letters, numbers, spaces, underscores, hyphens, periods, plus
            signs, apostrophes, and parentheses.
        parent_id: The ID of the Project or Folder that is the parent of this Folder.
        description: The description of this entity. Must be 1000 characters or less.
        etag: (Read Only)
            Synapse employs an Optimistic Concurrency Control (OCC) scheme to handle
            concurrent updates. Since the E-Tag changes every time an entity is updated
            it is used to detect when a client's current representation of an entity is
            out-of-date.
        created_on: (Read Only) The date this entity was created.
        modified_on: (Read Only) The date this entity was last modified.
        created_by: (Read Only) The ID of the user that created this entity.
        modified_by: (Read Only) The ID of the user that last modified this entity.
        files: Files that exist within this folder.
        folders: Folders that exist within this folder.
        tables: Tables that exist within this folder.
        entityviews: Entity views that exist within this folder.
        submissionviews: Submission views that exist within this folder.
        datasets: Datasets that exist within this folder.
        datasetcollections: Dataset collections that exist within this folder.
        materializedviews: Materialized views that exist within this folder.
        virtualtables: Virtual tables that exist within this folder.
        annotations: Additional metadata associated with the folder. The key is the name
            of your desired annotations. The value is an object containing a list of
            values (use empty list to represent no values for key) and the value type
            associated with all values in the list. To remove all annotations set this
            to an empty dict `{}` or None and store the entity.
        create_or_update: (Store only) Indicates whether the method should
            automatically perform an update if the resource conflicts with an existing
            Synapse object. When True this means that any changes to the resource will
            be non-destructive.

            This boolean is ignored if you've already stored or retrieved the resource
            from Synapse for this instance at least once. Any changes to the resource
            will be destructive in this case. For example if you want to delete the
            content for a field you will need to call `.get()` and then modify the
            field.
    """

    id: Optional[str] = None
    """The unique immutable ID for this folder. A new ID will be generated for new
    Folders. Once issued, this ID is guaranteed to never change or be re-issued"""

    name: Optional[str] = None
    """The name of this folder. Must be 256 characters or less. Names may only contain:
    letters, numbers, spaces, underscores, hyphens, periods, plus signs, apostrophes,
    and parentheses"""

    parent_id: Optional[str] = None
    """The ID of the Project or Folder that is the parent of this Folder."""

    description: Optional[str] = None
    """The description of this entity. Must be 1000 characters or less."""

    etag: Optional[str] = None
    """(Read Only)
    Synapse employs an Optimistic Concurrency Control (OCC) scheme to handle
    concurrent updates. Since the E-Tag changes every time an entity is updated it
    is used to detect when a client's current representation of an entity
    is out-of-date."""

    created_on: Optional[str] = None
    """(Read Only) The date this entity was created."""

    modified_on: Optional[str] = None
    """(Read Only) The date this entity was last modified."""

    created_by: Optional[str] = None
    """(Read Only) The ID of the user that created this entity."""

    modified_by: Optional[str] = None
    """(Read Only) The ID of the user that last modified this entity."""

    files: List["File"] = field(default_factory=list, compare=False)
    """Files that exist within this folder."""

    folders: List["Folder"] = field(default_factory=list, compare=False)
    """Folders that exist within this folder."""

    tables: List["Table"] = field(default_factory=list, compare=False)
    """Tables that exist within this folder."""

    entityviews: List["EntityView"] = field(default_factory=list, compare=False)
    """Entity views that exist within this folder."""

    submissionviews: List["SubmissionView"] = field(default_factory=list, compare=False)
    """Submission views that exist within this folder."""

    datasets: List["Dataset"] = field(default_factory=list, compare=False)
    """Datasets that exist within this folder."""

    datasetcollections: List["DatasetCollection"] = field(
        default_factory=list, compare=False
    )
    """Dataset collections that exist within this folder."""

    materializedviews: List["MaterializedView"] = field(
        default_factory=list, compare=False
    )
    """Materialized views that exist within this folder."""

    virtualtables: List["VirtualTable"] = field(default_factory=list, compare=False)
    """Virtual tables that exist within this folder."""

    annotations: Optional[
        Dict[
            str,
            Union[
                List[str],
                List[bool],
                List[float],
                List[int],
                List[date],
                List[datetime],
            ],
        ]
    ] = field(default_factory=dict, compare=False)
    """Additional metadata associated with the folder. The key is the name of your
    desired annotations. The value is an object containing a list of values
    (use empty list to represent no values for key) and the value type associated with
    all values in the list. To remove all annotations set this to an empty dict `{}`
    or None and store the entity."""

    is_restricted: bool = field(default=False, repr=False)
    """
    (Store only)

    If set to true, an email will be sent to the Synapse access control team to start
    the process of adding terms-of-use or review board approval for this entity.
    You will be contacted with regards to the specific data being restricted and the
    requirements of access.
    """

    create_or_update: bool = field(default=True, repr=False)
    """
    (Store only)

    Indicates whether the method should automatically perform an update if the resource
    conflicts with an existing Synapse object. When True this means that any changes
    to the resource will be non-destructive.

    This boolean is ignored if you've already stored or retrieved the resource from
    Synapse for this instance at least once. Any changes to the resource will be
    destructive in this case. For example if you want to delete the content for a field
    you will need to call `.get()` and then modify the field.
    """

    _last_persistent_instance: Optional["Folder"] = field(
        default=None, repr=False, compare=False
    )
    """The last persistent instance of this object. This is used to determine if the
    object has been changed and needs to be updated in Synapse."""

    _synced_from_synapse: Optional[bool] = field(
        default=False, repr=False, compare=False
    )
    """Whether this object has been synced from Synapse. This is used to determine if
    `.sync_from_synapse_async` has already been called on this instance."""

    @property
    def has_changed(self) -> bool:
        """Determines if the object has been changed and needs to be updated in Synapse."""
        return (
            not self._last_persistent_instance or self._last_persistent_instance != self
        )

    def _set_last_persistent_instance(self) -> None:
        """Stash the last time this object interacted with Synapse. This is used to
        determine if the object has been changed and needs to be updated in Synapse."""
        del self._last_persistent_instance
        self._last_persistent_instance = replace(self)
        self._last_persistent_instance.annotations = (
            deepcopy(self.annotations) if self.annotations else {}
        )

    def fill_from_dict(
        self, synapse_folder: Synapse_Folder, set_annotations: bool = True
    ) -> "Folder":
        """
        Converts a response from the REST API into this dataclass.

        Arguments:
            synapse_file: The response from the REST API.
            set_annotations: Whether to set the annotations from the response.

        Returns:
            The Folder object.
        """
        self.id = synapse_folder.get("id", None)
        self.name = synapse_folder.get("name", None)
        self.parent_id = synapse_folder.get("parentId", None)
        self.description = synapse_folder.get("description", None)
        self.etag = synapse_folder.get("etag", None)
        self.created_on = synapse_folder.get("createdOn", None)
        self.modified_on = synapse_folder.get("modifiedOn", None)
        self.created_by = synapse_folder.get("createdBy", None)
        self.modified_by = synapse_folder.get("modifiedBy", None)
        if set_annotations:
            self.annotations = Annotations.from_dict(
                synapse_folder.get("annotations", None)
            )
        return self

    @otel_trace_method(
        method_to_trace_name=lambda self, **kwargs: f"Folder_Store: {self.name}"
    )
    async def store_async(
        self,
        parent: Optional[Union["Folder", "Project"]] = None,
        failure_strategy: FailureStrategy = FailureStrategy.LOG_EXCEPTION,
        *,
        synapse_client: Optional[Synapse] = None,
    ) -> "Folder":
        """Store folders and files to synapse. If you have any files or folders attached
        to this folder they will be stored as well. You may attach files and folders
        to this folder by setting the `files` and `folders` attributes.

        By default the store operation will non-destructively update the folder if
        you have not already retrieved the folder from Synapse. If you have already
        retrieved the folder from Synapse then the store operation will be destructive
        and will overwrite the folder with the current state of this object. See the
        `create_or_update` attribute for more information.

        Arguments:
            parent: The parent folder or project to store the folder in.
            failure_strategy: Determines how to handle failures when storing attached
                Files and Folders under this Folder and an exception occurs.
            synapse_client: If not passed in and caching was not disabled by
                `Synapse.allow_client_caching(False)` this will use the last created
                instance from the Synapse class constructor.

        Returns:
            The folder object.

        Raises:
            ValueError: If the folder does not have an id or a
                (name and (`parent_id` or parent with an id)) set.
        """
        parent_id = parent.id if parent else self.parent_id
        if not (self.id or (self.name and parent_id)):
            raise ValueError(
                "The folder must have an id or a "
                "(name and (`parent_id` or parent with an id)) set."
            )
        self.parent_id = parent_id

        if (
            self.create_or_update
            and not self._last_persistent_instance
            and (
                existing_folder_id := await get_id(
                    entity=self, failure_strategy=None, synapse_client=synapse_client
                )
            )
            and (
                existing_folder := await Folder(id=existing_folder_id).get_async(
                    synapse_client=synapse_client
                )
            )
        ):
            merge_dataclass_entities(source=existing_folder, destination=self)
        trace.get_current_span().set_attributes(
            {
                "synapse.name": self.name or "",
                "synapse.id": self.id or "",
            }
        )
        if self.has_changed:
            synapse_folder = Synapse_Folder(
                id=self.id,
                name=self.name,
                parent=parent_id,
                etag=self.etag,
                description=self.description,
            )
            delete_none_keys(synapse_folder)
            entity = await store_entity(
                resource=self,
                entity=synapse_folder,
                synapse_client=synapse_client,
            )

            self.fill_from_dict(synapse_folder=entity, set_annotations=False)

        await store_entity_components(
            root_resource=self,
            failure_strategy=failure_strategy,
            synapse_client=synapse_client,
        )
        self._set_last_persistent_instance()
        Synapse.get_client(synapse_client=synapse_client).logger.debug(
            f"Saved Folder {self.name}, id: {self.id}: parent: {self.parent_id}"
        )

        return self

    @otel_trace_method(
        method_to_trace_name=lambda self, **kwargs: f"Folder_Get: {self.id}"
    )
    async def get_async(
        self,
        parent: Optional[Union["Folder", "Project"]] = None,
        *,
        synapse_client: Optional[Synapse] = None,
    ) -> "Folder":
        """Get the folder metadata from Synapse. You are able to find a folder by
        either the id or the name and parent_id.

        Arguments:
            parent: The parent folder or project this folder exists under.
            synapse_client: If not passed in and caching was not disabled by
                `Synapse.allow_client_caching(False)` this will use the last created
                instance from the Synapse class constructor.

        Returns:
            The folder object.

        Raises:
            ValueError: If the folder does not have an id or a
                (name and (`parent_id` or parent with an id)) set.
        """
        parent_id = parent.id if parent else self.parent_id
        if not (self.id or (self.name and parent_id)):
            raise ValueError(
                "The folder must have an id or a "
                "(name and (`parent_id` or parent with an id)) set."
            )
        self.parent_id = parent_id

        entity_id = await get_id(entity=self, synapse_client=synapse_client)

        await get_from_entity_factory(
            entity_to_update=self,
            synapse_id_or_path=entity_id,
            synapse_client=synapse_client,
        )

        self._set_last_persistent_instance()
        return self

    @otel_trace_method(
        method_to_trace_name=lambda self, **kwargs: f"Folder_Delete: {self.id}"
    )
    async def delete_async(self, *, synapse_client: Optional[Synapse] = None) -> None:
        """Delete the folder from Synapse by its id.

        Arguments:
            synapse_client: If not passed in and caching was not disabled by
                `Synapse.allow_client_caching(False)` this will use the last created
                instance from the Synapse class constructor.

        Returns:
            None

        Raises:
            ValueError: If the folder does not have an id set.
        """
        if not self.id:
            raise ValueError("The folder must have an id set.")
        loop = asyncio.get_event_loop()
        await loop.run_in_executor(
            None,
            lambda: Synapse.get_client(synapse_client=synapse_client).delete(
                obj=self.id,
            ),
        )

    @otel_trace_method(
        method_to_trace_name=lambda self, **kwargs: f"Folder_Copy: {self.id}"
    )
    async def copy_async(
        self,
        parent_id: str,
        copy_annotations: bool = True,
        exclude_types: Optional[List[str]] = None,
        file_update_existing: bool = False,
        file_copy_activity: Union[str, None] = "traceback",
        *,
        synapse_client: Optional[Synapse] = None,
    ) -> "Folder":
        """
        Copy the folder to another Synapse location. This will recursively copy all
        Tables, Links, Files, and Folders within the folder.

        Arguments:
            parent_id: Synapse ID of a folder/project that the copied entity is
                being copied to
            copy_annotations: True to copy the annotations.
            exclude_types: A list of entity types ['file', 'table', 'link'] which
                determines which entity types to not copy. Defaults to an empty list.
            file_update_existing: When the destination has a file that has the same name,
                users can choose to update that file.
            file_copy_activity: Has three options to set the activity of the copied file:

                    - traceback: Creates a copy of the source files Activity.
                    - existing: Link to the source file's original Activity (if it exists)
                    - None: No activity is set
            synapse_client: If not passed in and caching was not disabled by
                `Synapse.allow_client_caching(False)` this will use the last created
                instance from the Synapse class constructor.

        Returns:
            The copied folder object.

        Example: Using this function
            Assuming you have a folder with the ID "syn123" and you want to copy it to a
            project with the ID "syn456":

                new_folder_instance = await Folder(id="syn123").copy_async(parent_id="syn456")

            Copy the folder but do not persist annotations:

                new_folder_instance = await Folder(id="syn123").copy_async(parent_id="syn456", copy_annotations=False)

        Raises:
            ValueError: If the folder does not have an ID and parent_id to copy.
        """
        if not self.id or not parent_id:
            raise ValueError("The folder must have an ID and parent_id to copy.")

        loop = asyncio.get_event_loop()

        syn = Synapse.get_client(synapse_client=synapse_client)
        source_and_destination = await loop.run_in_executor(
            None,
            lambda: copy(
                syn=syn,
                entity=self.id,
                destinationId=parent_id,
                excludeTypes=exclude_types or [],
                skipCopyAnnotations=not copy_annotations,
                updateExisting=file_update_existing,
                setProvenance=file_copy_activity,
            ),
        )

        new_folder_id = source_and_destination.get(self.id, None)
        if not new_folder_id:
            raise SynapseError("Failed to copy folder.")
        folder_copy = await (
            await Folder(id=new_folder_id).get_async(synapse_client=synapse_client)
        ).sync_from_synapse_async(
            download_file=False,
            synapse_client=synapse_client,
        )
        syn.logger.debug(
            f"Copied from folder {self.id} to {parent_id} with new id of {folder_copy.id}"
        )
        return folder_copy

Functions

get

get(parent: Optional[Union[Folder, Project]] = None, *, synapse_client: Optional[Synapse] = None) -> Folder

Get the folder metadata from Synapse. You are able to find a folder by either the id or the name and parent_id.

PARAMETER DESCRIPTION
parent

The parent folder or project this folder exists under.

TYPE: Optional[Union[Folder, Project]] DEFAULT: None

synapse_client

If not passed in and caching was not disabled by Synapse.allow_client_caching(False) this will use the last created instance from the Synapse class constructor.

TYPE: Optional[Synapse] DEFAULT: None

RETURNS DESCRIPTION
Folder

The folder object.

RAISES DESCRIPTION
ValueError

If the folder does not have an id or a (name and (parent_id or parent with an id)) set.

Source code in synapseclient/models/protocols/folder_protocol.py
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
def get(
    self,
    parent: Optional[Union["Folder", "Project"]] = None,
    *,
    synapse_client: Optional[Synapse] = None,
) -> "Folder":
    """Get the folder metadata from Synapse. You are able to find a folder by
    either the id or the name and parent_id.

    Arguments:
        parent: The parent folder or project this folder exists under.
        synapse_client: If not passed in and caching was not disabled by
            `Synapse.allow_client_caching(False)` this will use the last created
            instance from the Synapse class constructor.

    Returns:
        The folder object.

    Raises:
        ValueError: If the folder does not have an id or a
            (name and (`parent_id` or parent with an id)) set.
    """
    return self

store

store(parent: Optional[Union[Folder, Project]] = None, failure_strategy: FailureStrategy = LOG_EXCEPTION, *, synapse_client: Optional[Synapse] = None) -> Folder

Store folders and files to synapse. If you have any files or folders attached to this folder they will be stored as well. You may attach files and folders to this folder by setting the files and folders attributes.

By default the store operation will non-destructively update the folder if you have not already retrieved the folder from Synapse. If you have already retrieved the folder from Synapse then the store operation will be destructive and will overwrite the folder with the current state of this object. See the create_or_update attribute for more information.

PARAMETER DESCRIPTION
parent

The parent folder or project to store the folder in.

TYPE: Optional[Union[Folder, Project]] DEFAULT: None

failure_strategy

Determines how to handle failures when storing attached Files and Folders under this Folder and an exception occurs.

TYPE: FailureStrategy DEFAULT: LOG_EXCEPTION

synapse_client

If not passed in and caching was not disabled by Synapse.allow_client_caching(False) this will use the last created instance from the Synapse class constructor.

TYPE: Optional[Synapse] DEFAULT: None

RETURNS DESCRIPTION
Folder

The folder object.

RAISES DESCRIPTION
ValueError

If the folder does not have an id or a (name and (parent_id or parent with an id)) set.

Source code in synapseclient/models/protocols/folder_protocol.py
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
def store(
    self,
    parent: Optional[Union["Folder", "Project"]] = None,
    failure_strategy: FailureStrategy = FailureStrategy.LOG_EXCEPTION,
    *,
    synapse_client: Optional[Synapse] = None,
) -> "Folder":
    """Store folders and files to synapse. If you have any files or folders attached
    to this folder they will be stored as well. You may attach files and folders
    to this folder by setting the `files` and `folders` attributes.

    By default the store operation will non-destructively update the folder if
    you have not already retrieved the folder from Synapse. If you have already
    retrieved the folder from Synapse then the store operation will be destructive
    and will overwrite the folder with the current state of this object. See the
    `create_or_update` attribute for more information.

    Arguments:
        parent: The parent folder or project to store the folder in.
        failure_strategy: Determines how to handle failures when storing attached
            Files and Folders under this Folder and an exception occurs.
        synapse_client: If not passed in and caching was not disabled by
            `Synapse.allow_client_caching(False)` this will use the last created
            instance from the Synapse class constructor.

    Returns:
        The folder object.

    Raises:
        ValueError: If the folder does not have an id or a
            (name and (`parent_id` or parent with an id)) set.
    """
    return self

delete

delete(*, synapse_client: Optional[Synapse] = None) -> None

Delete the folder from Synapse by its id.

PARAMETER DESCRIPTION
synapse_client

If not passed in and caching was not disabled by Synapse.allow_client_caching(False) this will use the last created instance from the Synapse class constructor.

TYPE: Optional[Synapse] DEFAULT: None

RETURNS DESCRIPTION
None

None

RAISES DESCRIPTION
ValueError

If the folder does not have an id set.

Source code in synapseclient/models/protocols/folder_protocol.py
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
def delete(self, *, synapse_client: Optional[Synapse] = None) -> None:
    """Delete the folder from Synapse by its id.

    Arguments:
        synapse_client: If not passed in and caching was not disabled by
            `Synapse.allow_client_caching(False)` this will use the last created
            instance from the Synapse class constructor.

    Returns:
        None

    Raises:
        ValueError: If the folder does not have an id set.
    """
    return None

copy

copy(parent_id: str, copy_annotations: bool = True, exclude_types: Optional[List[str]] = None, file_update_existing: bool = False, file_copy_activity: Union[str, None] = 'traceback', *, synapse_client: Optional[Synapse] = None) -> Folder

Copy the folder to another Synapse location. This will recursively copy all Tables, Links, Files, and Folders within the folder.

PARAMETER DESCRIPTION
parent_id

Synapse ID of a folder/project that the copied entity is being copied to

TYPE: str

copy_annotations

True to copy the annotations.

TYPE: bool DEFAULT: True

exclude_types

A list of entity types ['file', 'table', 'link'] which determines which entity types to not copy. Defaults to an empty list.

TYPE: Optional[List[str]] DEFAULT: None

file_update_existing

When the destination has a file that has the same name, users can choose to update that file.

TYPE: bool DEFAULT: False

file_copy_activity

Has three options to set the activity of the copied file:

- traceback: Creates a copy of the source files Activity.
- existing: Link to the source file's original Activity (if it exists)
- None: No activity is set

TYPE: Union[str, None] DEFAULT: 'traceback'

synapse_client

If not passed in and caching was not disabled by Synapse.allow_client_caching(False) this will use the last created instance from the Synapse class constructor.

TYPE: Optional[Synapse] DEFAULT: None

RETURNS DESCRIPTION
Folder

The copied folder object.

Using this function

Assuming you have a folder with the ID "syn123" and you want to copy it to a project with the ID "syn456":

new_folder_instance = await Folder(id="syn123").copy(parent_id="syn456")

Copy the folder but do not persist annotations:

new_folder_instance = await Folder(id="syn123").copy(parent_id="syn456", copy_annotations=False)
RAISES DESCRIPTION
ValueError

If the folder does not have an ID and parent_id to copy.

Source code in synapseclient/models/protocols/folder_protocol.py
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
def copy(
    self,
    parent_id: str,
    copy_annotations: bool = True,
    exclude_types: Optional[List[str]] = None,
    file_update_existing: bool = False,
    file_copy_activity: Union[str, None] = "traceback",
    *,
    synapse_client: Optional[Synapse] = None,
) -> "Folder":
    """
    Copy the folder to another Synapse location. This will recursively copy all
    Tables, Links, Files, and Folders within the folder.

    Arguments:
        parent_id: Synapse ID of a folder/project that the copied entity is
            being copied to
        copy_annotations: True to copy the annotations.
        exclude_types: A list of entity types ['file', 'table', 'link'] which
            determines which entity types to not copy. Defaults to an empty list.
        file_update_existing: When the destination has a file that has the same name,
            users can choose to update that file.
        file_copy_activity: Has three options to set the activity of the copied file:

                - traceback: Creates a copy of the source files Activity.
                - existing: Link to the source file's original Activity (if it exists)
                - None: No activity is set
        synapse_client: If not passed in and caching was not disabled by
            `Synapse.allow_client_caching(False)` this will use the last created
            instance from the Synapse class constructor.

    Returns:
        The copied folder object.

    Example: Using this function
        Assuming you have a folder with the ID "syn123" and you want to copy it to a
        project with the ID "syn456":

            new_folder_instance = await Folder(id="syn123").copy(parent_id="syn456")

        Copy the folder but do not persist annotations:

            new_folder_instance = await Folder(id="syn123").copy(parent_id="syn456", copy_annotations=False)

    Raises:
        ValueError: If the folder does not have an ID and parent_id to copy.
    """
    return self

sync_from_synapse

sync_from_synapse(path: Optional[str] = None, recursive: bool = True, download_file: bool = True, if_collision: str = COLLISION_OVERWRITE_LOCAL, failure_strategy: FailureStrategy = LOG_EXCEPTION, include_activity: bool = True, follow_link: bool = False, link_hops: int = 1, queue: Queue = None, include_types: Optional[List[str]] = None, *, synapse_client: Optional[Synapse] = None) -> Self

Sync this container and all possible sub-folders from Synapse. By default this will download the files that are found and it will populate the files and folders attributes with the found files and folders, along with all other entity types (tables, entityviews, etc.) present in the container. If you only want to retrieve the full tree of metadata about your container specify download_file as False.

This works similar to synapseutils.syncFromSynapse, however, this does not currently support the writing of data to a manifest TSV file. This will be a future enhancement.

Supports syncing Files, Folders, Tables, EntityViews, SubmissionViews, Datasets, DatasetCollections, MaterializedViews, and VirtualTables from Synapse. The metadata for these entity types will be populated in their respective attributes (files, folders, tables, entityviews, submissionviews, datasets, datasetcollections, materializedviews, virtualtables) if they are found within the container.

PARAMETER DESCRIPTION
path

An optional path where the file hierarchy will be reproduced. If not specified the files will by default be placed in the synapseCache.

TYPE: Optional[str] DEFAULT: None

recursive

Whether or not to recursively get the entire hierarchy of the folder and sub-folders.

TYPE: bool DEFAULT: True

download_file

Whether to download the files found or not.

TYPE: bool DEFAULT: True

if_collision

Determines how to handle file collisions. May be

  • overwrite.local
  • keep.local
  • keep.both

TYPE: str DEFAULT: COLLISION_OVERWRITE_LOCAL

failure_strategy

Determines how to handle failures when retrieving children under this Folder and an exception occurs.

TYPE: FailureStrategy DEFAULT: LOG_EXCEPTION

include_activity

Whether to include the activity of the files.

TYPE: bool DEFAULT: True

follow_link

Whether to follow a link entity or not. Links can be used to point at other Synapse entities.

TYPE: bool DEFAULT: False

link_hops

The number of hops to follow the link. A number of 1 is used to prevent circular references. There is nothing in place to prevent infinite loops. Be careful if setting this above 1.

TYPE: int DEFAULT: 1

queue

An optional queue to use to download files in parallel.

TYPE: Queue DEFAULT: None

include_types

Must be a list of entity types (ie. ["folder","file"]) which can be found here

TYPE: Optional[List[str]] DEFAULT: None

synapse_client

If not passed in and caching was not disabled by Synapse.allow_client_caching(False) this will use the last created instance from the Synapse class constructor.

TYPE: Optional[Synapse] DEFAULT: None

RETURNS DESCRIPTION
Self

The object that was called on. This will be the same object that was called on to start the sync.

Using this function

Suppose I want to walk the immediate children of a folder without downloading the files:

from synapseclient import Synapse
from synapseclient.models import Folder

syn = Synapse()
syn.login()

my_folder = Folder(id="syn12345")
my_folder.sync_from_synapse(download_file=False, recursive=False)

for folder in my_folder.folders:
    print(folder.name)

for file in my_folder.files:
    print(file.name)

for table in my_folder.tables:
    print(table.name)

for dataset in my_folder.datasets:
    print(dataset.name)

Suppose I want to download the immediate children of a folder:

from synapseclient import Synapse
from synapseclient.models import Folder

syn = Synapse()
syn.login()

my_folder = Folder(id="syn12345")
my_folder.sync_from_synapse(path="/path/to/folder", recursive=False)

for folder in my_folder.folders:
    print(folder.name)

for file in my_folder.files:
    print(file.name)

Suppose I want to sync only specific entity types from a Project:

from synapseclient import Synapse
from synapseclient.models import Project

syn = Synapse()
syn.login()

my_project = Project(id="syn12345")
my_project.sync_from_synapse(
    path="/path/to/folder",
    include_types=["folder", "file", "table", "dataset"]
)

# Access different entity types
for table in my_project.tables:
    print(f"Table: {table.name}")

for dataset in my_project.datasets:
    print(f"Dataset: {dataset.name}")

Suppose I want to download all the children of a Project and all sub-folders and files:

from synapseclient import Synapse
from synapseclient.models import Project

syn = Synapse()
syn.login()

my_project = Project(id="syn12345")
my_project.sync_from_synapse(path="/path/to/folder")
RAISES DESCRIPTION
ValueError

If the folder does not have an id set.

A sequence diagram for this method is as follows:

sequenceDiagram
    autonumber
    participant project_or_folder
    activate project_or_folder
    project_or_folder->>sync_from_synapse: Recursive search and download files
    activate sync_from_synapse
        opt Current instance not retrieved from Synapse
            sync_from_synapse->>project_or_folder: Call `.get()` method
            project_or_folder-->>sync_from_synapse: .
        end

        loop For each return of the generator
            sync_from_synapse->>client: call `.getChildren()` method
            client-->>sync_from_synapse: .
            note over sync_from_synapse: Append to a running list
        end

        loop For each child
            note over sync_from_synapse: Create all `pending_tasks` at current depth

            alt Child is File
                note over sync_from_synapse: Append `file.get()` method
            else Child is Folder
                note over sync_from_synapse: Append `folder.get()` method
                alt Recursive is True
                    note over sync_from_synapse: Append `folder.sync_from_synapse()` method
                end
            end
        end

        loop For each task in pending_tasks
            par `file.get()`
                sync_from_synapse->>File: Retrieve File metadata and Optionally download
                File->>client: `.get()`
                client-->>File: .
                File-->>sync_from_synapse: .
            and `folder.get()`
                sync_from_synapse->>Folder: Retrieve Folder metadataa
                Folder->>client: `.get()`
                client-->>Folder: .
                Folder-->>sync_from_synapse: .
            and `folder.sync_from_synapse()`
                note over sync_from_synapse: This is a recursive call to `sync_from_synapse`
                sync_from_synapse->>sync_from_synapse: Recursive call to `.sync_from_synapse()`
            end
        end

    deactivate sync_from_synapse
    deactivate project_or_folder
Source code in synapseclient/models/protocols/storable_container_protocol.py
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
def sync_from_synapse(
    self: Self,
    path: Optional[str] = None,
    recursive: bool = True,
    download_file: bool = True,
    if_collision: str = COLLISION_OVERWRITE_LOCAL,
    failure_strategy: FailureStrategy = FailureStrategy.LOG_EXCEPTION,
    include_activity: bool = True,
    follow_link: bool = False,
    link_hops: int = 1,
    queue: asyncio.Queue = None,
    include_types: Optional[List[str]] = None,
    *,
    synapse_client: Optional[Synapse] = None,
) -> Self:
    """
    Sync this container and all possible sub-folders from Synapse. By default this
    will download the files that are found and it will populate the
    `files` and `folders` attributes with the found files and folders, along with
    all other entity types (tables, entityviews, etc.) present in the container.
    If you only want to retrieve the full tree of metadata about your
    container specify `download_file` as False.

    This works similar to [synapseutils.syncFromSynapse][], however, this does not
    currently support the writing of data to a manifest TSV file. This will be a
    future enhancement.

    Supports syncing Files, Folders, Tables, EntityViews, SubmissionViews, Datasets,
    DatasetCollections, MaterializedViews, and VirtualTables from Synapse. The
    metadata for these entity types will be populated in their respective
    attributes (`files`, `folders`, `tables`, `entityviews`, `submissionviews`,
    `datasets`, `datasetcollections`, `materializedviews`, `virtualtables`) if
    they are found within the container.

    Arguments:
        path: An optional path where the file hierarchy will be reproduced. If not
            specified the files will by default be placed in the synapseCache.
        recursive: Whether or not to recursively get the entire hierarchy of the
            folder and sub-folders.
        download_file: Whether to download the files found or not.
        if_collision: Determines how to handle file collisions. May be

            - `overwrite.local`
            - `keep.local`
            - `keep.both`
        failure_strategy: Determines how to handle failures when retrieving children
            under this Folder and an exception occurs.
        include_activity: Whether to include the activity of the files.
        follow_link: Whether to follow a link entity or not. Links can be used to
            point at other Synapse entities.
        link_hops: The number of hops to follow the link. A number of 1 is used to
            prevent circular references. There is nothing in place to prevent
            infinite loops. Be careful if setting this above 1.
        queue: An optional queue to use to download files in parallel.
        include_types: Must be a list of entity types (ie. ["folder","file"]) which
            can be found
            [here](https://rest-docs.synapse.org/rest/org/sagebionetworks/repo/model/EntityType.html)
        synapse_client: If not passed in and caching was not disabled by
            `Synapse.allow_client_caching(False)` this will use the last created
            instance from the Synapse class constructor.

    Returns:
        The object that was called on. This will be the same object that was called on
            to start the sync.

    Example: Using this function
        Suppose I want to walk the immediate children of a folder without downloading the files:

        ```python
        from synapseclient import Synapse
        from synapseclient.models import Folder

        syn = Synapse()
        syn.login()

        my_folder = Folder(id="syn12345")
        my_folder.sync_from_synapse(download_file=False, recursive=False)

        for folder in my_folder.folders:
            print(folder.name)

        for file in my_folder.files:
            print(file.name)

        for table in my_folder.tables:
            print(table.name)

        for dataset in my_folder.datasets:
            print(dataset.name)
        ```

        Suppose I want to download the immediate children of a folder:

        ```python
        from synapseclient import Synapse
        from synapseclient.models import Folder

        syn = Synapse()
        syn.login()

        my_folder = Folder(id="syn12345")
        my_folder.sync_from_synapse(path="/path/to/folder", recursive=False)

        for folder in my_folder.folders:
            print(folder.name)

        for file in my_folder.files:
            print(file.name)
        ```

        Suppose I want to sync only specific entity types from a Project:

        ```python
        from synapseclient import Synapse
        from synapseclient.models import Project

        syn = Synapse()
        syn.login()

        my_project = Project(id="syn12345")
        my_project.sync_from_synapse(
            path="/path/to/folder",
            include_types=["folder", "file", "table", "dataset"]
        )

        # Access different entity types
        for table in my_project.tables:
            print(f"Table: {table.name}")

        for dataset in my_project.datasets:
            print(f"Dataset: {dataset.name}")
        ```

        Suppose I want to download all the children of a Project and all sub-folders and files:

        ```python
        from synapseclient import Synapse
        from synapseclient.models import Project

        syn = Synapse()
        syn.login()

        my_project = Project(id="syn12345")
        my_project.sync_from_synapse(path="/path/to/folder")
        ```


    Raises:
        ValueError: If the folder does not have an id set.


    A sequence diagram for this method is as follows:

    ```mermaid
    sequenceDiagram
        autonumber
        participant project_or_folder
        activate project_or_folder
        project_or_folder->>sync_from_synapse: Recursive search and download files
        activate sync_from_synapse
            opt Current instance not retrieved from Synapse
                sync_from_synapse->>project_or_folder: Call `.get()` method
                project_or_folder-->>sync_from_synapse: .
            end

            loop For each return of the generator
                sync_from_synapse->>client: call `.getChildren()` method
                client-->>sync_from_synapse: .
                note over sync_from_synapse: Append to a running list
            end

            loop For each child
                note over sync_from_synapse: Create all `pending_tasks` at current depth

                alt Child is File
                    note over sync_from_synapse: Append `file.get()` method
                else Child is Folder
                    note over sync_from_synapse: Append `folder.get()` method
                    alt Recursive is True
                        note over sync_from_synapse: Append `folder.sync_from_synapse()` method
                    end
                end
            end

            loop For each task in pending_tasks
                par `file.get()`
                    sync_from_synapse->>File: Retrieve File metadata and Optionally download
                    File->>client: `.get()`
                    client-->>File: .
                    File-->>sync_from_synapse: .
                and `folder.get()`
                    sync_from_synapse->>Folder: Retrieve Folder metadataa
                    Folder->>client: `.get()`
                    client-->>Folder: .
                    Folder-->>sync_from_synapse: .
                and `folder.sync_from_synapse()`
                    note over sync_from_synapse: This is a recursive call to `sync_from_synapse`
                    sync_from_synapse->>sync_from_synapse: Recursive call to `.sync_from_synapse()`
                end
            end

        deactivate sync_from_synapse
        deactivate project_or_folder
    ```

    """
    return self

flatten_file_list

flatten_file_list() -> List[File]

Recursively loop over all of the already retrieved files and folders and return a list of all files in the container.

RETURNS DESCRIPTION
List[File]

A list of all files in the container.

Source code in synapseclient/models/mixins/storable_container.py
483
484
485
486
487
488
489
490
491
492
493
494
495
496
def flatten_file_list(self) -> List["File"]:
    """
    Recursively loop over all of the already retrieved files and folders and return
    a list of all files in the container.

    Returns:
        A list of all files in the container.
    """
    files = []
    for file in self.files:
        files.append(file)
    for folder in self.folders:
        files.extend(folder.flatten_file_list())
    return files

map_directory_to_all_contained_files

map_directory_to_all_contained_files(root_path: str) -> Dict[str, List[File]]

Recursively loop over all of the already retrieved files and folders. Then return back a dictionary where the key is the path to the directory at each level. The value is a list of all files in that directory AND all files in the child directories.

This is used during the creation of the manifest TSV file during the syncFromSynapse utility function.

Using this function

Returning back a dict with 2 keys:

 Given:
 root_folder
 ├── sub_folder
 │   ├── file1.txt
 │   └── file2.txt

 Returns:
 {
     "root_folder": [file1, file2],
     "root_folder/sub_folder": [file1, file2]
 }

Returning back a dict with 3 keys:

 Given:
 root_folder
 ├── sub_folder_1
 │   ├── file1.txt
 ├── sub_folder_2
 │   └── file2.txt

 Returns:
 {
     "root_folder": [file1, file2],
     "root_folder/sub_folder_1": [file1]
     "root_folder/sub_folder_2": [file2]
 }
PARAMETER DESCRIPTION
root_path

The root path where the top level files are stored.

TYPE: str

RETURNS DESCRIPTION
Dict[str, List[File]]

A dictionary where the key is the path to the directory at each level. The value is a list of all files in that directory AND all files in the child directories.

Source code in synapseclient/models/mixins/storable_container.py
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
def map_directory_to_all_contained_files(
    self, root_path: str
) -> Dict[str, List["File"]]:
    """
    Recursively loop over all of the already retrieved files and folders. Then
    return back a dictionary where the key is the path to the directory at each
    level. The value is a list of all files in that directory AND all files in
    the child directories.

    This is used during the creation of the manifest TSV file during the
    syncFromSynapse utility function.

    Example: Using this function
       Returning back a dict with 2 keys:

            Given:
            root_folder
            ├── sub_folder
            │   ├── file1.txt
            │   └── file2.txt

            Returns:
            {
                "root_folder": [file1, file2],
                "root_folder/sub_folder": [file1, file2]
            }


       Returning back a dict with 3 keys:

            Given:
            root_folder
            ├── sub_folder_1
            │   ├── file1.txt
            ├── sub_folder_2
            │   └── file2.txt

            Returns:
            {
                "root_folder": [file1, file2],
                "root_folder/sub_folder_1": [file1]
                "root_folder/sub_folder_2": [file2]
            }

    Arguments:
        root_path: The root path where the top level files are stored.

    Returns:
        A dictionary where the key is the path to the directory at each level. The
            value is a list of all files in that directory AND all files in the child
            directories.
    """
    directory_map = {}
    directory_map.update({root_path: self.flatten_file_list()})

    for folder in self.folders:
        directory_map.update(
            **folder.map_directory_to_all_contained_files(
                root_path=os.path.join(root_path, folder.name)
            )
        )

    return directory_map

get_permissions

get_permissions(*, synapse_client: Optional[Synapse] = None) -> Permissions

Get the permissions that the caller has on an Entity.

PARAMETER DESCRIPTION
synapse_client

If not passed in and caching was not disabled by Synapse.allow_client_caching(False) this will use the last created instance from the Synapse class constructor.

TYPE: Optional[Synapse] DEFAULT: None

RETURNS DESCRIPTION
Permissions

A Permissions object

Using this function:

Getting permissions for a Synapse Entity

from synapseclient import Synapse
from synapseclient.models import File

syn = Synapse()
syn.login()

permissions = File(id="syn123").get_permissions()

Getting access types list from the Permissions object

permissions.access_types
Source code in synapseclient/models/protocols/access_control_protocol.py
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
def get_permissions(
    self,
    *,
    synapse_client: Optional[Synapse] = None,
) -> "Permissions":
    """
    Get the [permissions][synapseclient.core.models.permission.Permissions]
    that the caller has on an Entity.

    Arguments:
        synapse_client: If not passed in and caching was not disabled by
            `Synapse.allow_client_caching(False)` this will use the last created
            instance from the Synapse class constructor.

    Returns:
        A Permissions object


    Example: Using this function:
        Getting permissions for a Synapse Entity

        ```python
        from synapseclient import Synapse
        from synapseclient.models import File

        syn = Synapse()
        syn.login()

        permissions = File(id="syn123").get_permissions()
        ```

        Getting access types list from the Permissions object

        ```
        permissions.access_types
        ```
    """
    return self

get_acl

get_acl(principal_id: int = None, check_benefactor: bool = True, *, synapse_client: Optional[Synapse] = None) -> List[str]

Get the ACL that a user or group has on an Entity.

Note: If the entity does not have local sharing settings, or ACL set directly on it, this will look up the ACL on the benefactor of the entity. The benefactor is the entity that the current entity inherits its permissions from. The benefactor is usually the parent entity, but it can be any ancestor in the hierarchy. For example, a newly created Project will be its own benefactor, while a new FileEntity's benefactor will start off as its containing Project or Folder. If the entity already has local sharing settings, the benefactor would be itself.

PARAMETER DESCRIPTION
principal_id

Identifier of a user or group (defaults to PUBLIC users)

TYPE: int DEFAULT: None

check_benefactor

If True (default), check the benefactor for the entity to get the ACL. If False, only check the entity itself. This is useful for checking the ACL of an entity that has local sharing settings, but you want to check the ACL of the entity itself and not the benefactor it may inherit from.

TYPE: bool DEFAULT: True

synapse_client

If not passed in and caching was not disabled by Synapse.allow_client_caching(False) this will use the last created instance from the Synapse class constructor.

TYPE: Optional[Synapse] DEFAULT: None

RETURNS DESCRIPTION
List[str]

An array containing some combination of ['READ', 'UPDATE', 'CREATE', 'DELETE', 'DOWNLOAD', 'MODERATE', 'CHANGE_PERMISSIONS', 'CHANGE_SETTINGS'] or an empty array

Source code in synapseclient/models/protocols/access_control_protocol.py
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
def get_acl(
    self,
    principal_id: int = None,
    check_benefactor: bool = True,
    *,
    synapse_client: Optional[Synapse] = None,
) -> List[str]:
    """
    Get the [ACL][synapseclient.core.models.permission.Permissions.access_types]
    that a user or group has on an Entity.

    Note: If the entity does not have local sharing settings, or ACL set directly
    on it, this will look up the ACL on the benefactor of the entity. The
    benefactor is the entity that the current entity inherits its permissions from.
    The benefactor is usually the parent entity, but it can be any ancestor in the
    hierarchy. For example, a newly created Project will be its own benefactor,
    while a new FileEntity's benefactor will start off as its containing Project or
    Folder. If the entity already has local sharing settings, the benefactor would
    be itself.

    Arguments:
        principal_id: Identifier of a user or group (defaults to PUBLIC users)
        check_benefactor: If True (default), check the benefactor for the entity
            to get the ACL. If False, only check the entity itself.
            This is useful for checking the ACL of an entity that has local sharing
            settings, but you want to check the ACL of the entity itself and not
            the benefactor it may inherit from.
        synapse_client: If not passed in and caching was not disabled by
            `Synapse.allow_client_caching(False)` this will use the last created
            instance from the Synapse class constructor.

    Returns:
        An array containing some combination of
            ['READ', 'UPDATE', 'CREATE', 'DELETE', 'DOWNLOAD', 'MODERATE',
            'CHANGE_PERMISSIONS', 'CHANGE_SETTINGS']
            or an empty array
    """
    return [""]

list_acl

list_acl(recursive: bool = False, include_container_content: bool = False, target_entity_types: Optional[List[str]] = None, log_tree: bool = False, *, synapse_client: Optional[Synapse] = None, _progress_bar: Optional[tqdm] = None) -> AclListResult

List the Access Control Lists (ACLs) for this entity and optionally its children.

This function returns the local sharing settings for the entity and optionally its children. It provides a mapping of all ACLs for the given container/entity.

Important Note: This function returns the LOCAL sharing settings only, not the effective permissions that each Synapse User ID/Team has on the entities. More permissive permissions could be granted via a Team that the user has access to that has permissions on the entity, or through inheritance from parent entities.

PARAMETER DESCRIPTION
recursive

If True and the entity is a container (e.g., Project or Folder), recursively process child containers. Note that this must be used with include_container_content=True to have any effect. Setting recursive=True with include_container_content=False will raise a ValueError. Only works on classes that support the sync_from_synapse_async method.

TYPE: bool DEFAULT: False

include_container_content

If True, include ACLs from contents directly within containers (files and folders inside self). This must be set to True for recursive to have any effect. Defaults to False.

TYPE: bool DEFAULT: False

target_entity_types

Specify which entity types to process when listing ACLs. Allowed values are "folder" and "file" (case-insensitive). If None, defaults to ["folder", "file"].

TYPE: Optional[List[str]] DEFAULT: None

log_tree

If True, logs the ACL results to console in ASCII tree format showing entity hierarchies and their ACL permissions in a tree-like structure. Defaults to False.

TYPE: bool DEFAULT: False

synapse_client

If not passed in and caching was not disabled by Synapse.allow_client_caching(False) this will use the last created instance from the Synapse class constructor.

TYPE: Optional[Synapse] DEFAULT: None

_progress_bar

Internal parameter. Progress bar instance to use for updates when called recursively. Should not be used by external callers.

TYPE: Optional[tqdm] DEFAULT: None

RETURNS DESCRIPTION
AclListResult

An AclListResult object containing a structured representation of ACLs where:

AclListResult
  • entity_acls: A list of EntityAcl objects, each representing one entity's ACL
AclListResult
  • Each EntityAcl contains acl_entries (a list of AclEntry objects)
AclListResult
  • Each AclEntry contains the principal_id and their list of permissions
RAISES DESCRIPTION
ValueError

If the entity does not have an ID or if an invalid entity type is provided.

SynapseHTTPError

If there are permission issues accessing ACLs.

Exception

For any other errors that may occur during the process.

List ACLs for a single entity
from synapseclient import Synapse
from synapseclient.models import File

syn = Synapse()
syn.login()

acl_result = File(id="syn123").list_acl()
print(acl_result)

# Access entity ACLs (entity_acls is a list, not a dict)
for entity_acl in acl_result.all_entity_acls:
    if entity_acl.entity_id == "syn123":
        # Access individual ACL entries
        for acl_entry in entity_acl.acl_entries:
            if acl_entry.principal_id == "273948":
                print(f"Principal 273948 has permissions: {acl_entry.permissions}")

# I can also access the ACL for the file itself
print(acl_result.entity_acl)

print(acl_result)
List ACLs recursively for a folder and all its children
from synapseclient import Synapse
from synapseclient.models import Folder

syn = Synapse()
syn.login()

acl_result = Folder(id="syn123").list_acl(
    recursive=True,
    include_container_content=True
)

# Access each entity's ACL (entity_acls is a list)
for entity_acl in acl_result.all_entity_acls:
    print(f"Entity {entity_acl.entity_id} has ACL with {len(entity_acl.acl_entries)} principals")

# I can also access the ACL for the folder itself
print(acl_result.entity_acl)

# List ACLs for only folder entities
folder_acl_result = Folder(id="syn123").list_acl(
    recursive=True,
    include_container_content=True,
    target_entity_types=["folder"]
)
List ACLs with ASCII tree visualization

When log_tree=True, the ACLs will be logged in a tree format. Additionally, the ascii_tree attribute of the AclListResult will contain the ASCII tree representation of the ACLs.

from synapseclient import Synapse
from synapseclient.models import Folder

syn = Synapse()
syn.login()

acl_result = Folder(id="syn123").list_acl(
    recursive=True,
    include_container_content=True,
    log_tree=True, # Enable ASCII tree logging
)

# The ASCII tree representation of the ACLs will also be available
# in acl_result.ascii_tree
print(acl_result.ascii_tree)
Source code in synapseclient/models/protocols/access_control_protocol.py
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
def list_acl(
    self,
    recursive: bool = False,
    include_container_content: bool = False,
    target_entity_types: Optional[List[str]] = None,
    log_tree: bool = False,
    *,
    synapse_client: Optional[Synapse] = None,
    _progress_bar: Optional[tqdm] = None,  # Internal parameter for recursive calls
) -> "AclListResult":
    """
    List the Access Control Lists (ACLs) for this entity and optionally its children.

    This function returns the local sharing settings for the entity and optionally
    its children. It provides a mapping of all ACLs for the given container/entity.

    **Important Note:** This function returns the LOCAL sharing settings only, not
    the effective permissions that each Synapse User ID/Team has on the entities.
    More permissive permissions could be granted via a Team that the user has access
    to that has permissions on the entity, or through inheritance from parent entities.

    Arguments:
        recursive: If True and the entity is a container (e.g., Project or Folder),
            recursively process child containers. Note that this must be used with
            include_container_content=True to have any effect. Setting recursive=True
            with include_container_content=False will raise a ValueError.
            Only works on classes that support the `sync_from_synapse_async` method.
        include_container_content: If True, include ACLs from contents directly within
            containers (files and folders inside self). This must be set to
            True for recursive to have any effect. Defaults to False.
        target_entity_types: Specify which entity types to process when listing ACLs.
            Allowed values are "folder" and "file" (case-insensitive).
            If None, defaults to ["folder", "file"].
        log_tree: If True, logs the ACL results to console in ASCII tree format showing
            entity hierarchies and their ACL permissions in a tree-like structure.
            Defaults to False.
        synapse_client: If not passed in and caching was not disabled by
            `Synapse.allow_client_caching(False)` this will use the last created
            instance from the Synapse class constructor.
        _progress_bar: Internal parameter. Progress bar instance to use for updates
            when called recursively. Should not be used by external callers.

    Returns:
        An AclListResult object containing a structured representation of ACLs where:
        - entity_acls: A list of EntityAcl objects, each representing one entity's ACL
        - Each EntityAcl contains acl_entries (a list of AclEntry objects)
        - Each AclEntry contains the principal_id and their list of permissions

    Raises:
        ValueError: If the entity does not have an ID or if an invalid entity type is provided.
        SynapseHTTPError: If there are permission issues accessing ACLs.
        Exception: For any other errors that may occur during the process.

    Example: List ACLs for a single entity
        ```python
        from synapseclient import Synapse
        from synapseclient.models import File

        syn = Synapse()
        syn.login()

        acl_result = File(id="syn123").list_acl()
        print(acl_result)

        # Access entity ACLs (entity_acls is a list, not a dict)
        for entity_acl in acl_result.all_entity_acls:
            if entity_acl.entity_id == "syn123":
                # Access individual ACL entries
                for acl_entry in entity_acl.acl_entries:
                    if acl_entry.principal_id == "273948":
                        print(f"Principal 273948 has permissions: {acl_entry.permissions}")

        # I can also access the ACL for the file itself
        print(acl_result.entity_acl)

        print(acl_result)

        ```

    Example: List ACLs recursively for a folder and all its children
        ```python
        from synapseclient import Synapse
        from synapseclient.models import Folder

        syn = Synapse()
        syn.login()

        acl_result = Folder(id="syn123").list_acl(
            recursive=True,
            include_container_content=True
        )

        # Access each entity's ACL (entity_acls is a list)
        for entity_acl in acl_result.all_entity_acls:
            print(f"Entity {entity_acl.entity_id} has ACL with {len(entity_acl.acl_entries)} principals")

        # I can also access the ACL for the folder itself
        print(acl_result.entity_acl)

        # List ACLs for only folder entities
        folder_acl_result = Folder(id="syn123").list_acl(
            recursive=True,
            include_container_content=True,
            target_entity_types=["folder"]
        )
        ```

    Example: List ACLs with ASCII tree visualization
        When `log_tree=True`, the ACLs will be logged in a tree format. Additionally,
        the `ascii_tree` attribute of the AclListResult will contain the ASCII tree
        representation of the ACLs.

        ```python
        from synapseclient import Synapse
        from synapseclient.models import Folder

        syn = Synapse()
        syn.login()

        acl_result = Folder(id="syn123").list_acl(
            recursive=True,
            include_container_content=True,
            log_tree=True, # Enable ASCII tree logging
        )

        # The ASCII tree representation of the ACLs will also be available
        # in acl_result.ascii_tree
        print(acl_result.ascii_tree)
        ```
    """
    return AclListResult()

set_permissions

set_permissions(principal_id: int = None, access_type: List[str] = None, modify_benefactor: bool = False, warn_if_inherits: bool = True, overwrite: bool = True, *, synapse_client: Optional[Synapse] = None) -> Dict[str, Union[str, list]]

Sets permission that a user or group has on an Entity. An Entity may have its own ACL or inherit its ACL from a benefactor.

PARAMETER DESCRIPTION
principal_id

Identifier of a user or group. 273948 is for all registered Synapse users and 273949 is for public access. None implies public access.

TYPE: int DEFAULT: None

access_type

Type of permission to be granted. One or more of CREATE, READ, DOWNLOAD, UPDATE, DELETE, CHANGE_PERMISSIONS.

Defaults to ['READ', 'DOWNLOAD']

TYPE: List[str] DEFAULT: None

modify_benefactor

Set as True when modifying a benefactor's ACL. The term 'benefactor' is used to indicate which Entity an Entity inherits its ACL from. For example, a newly created Project will be its own benefactor, while a new FileEntity's benefactor will start off as its containing Project. If the entity already has local sharing settings the benefactor would be itself. It may also be the immediate parent, somewhere in the parent tree, or the project itself.

TYPE: bool DEFAULT: False

warn_if_inherits

When modify_benefactor is True, this does not have any effect. When modify_benefactor is False, and warn_if_inherits is True, a warning log message is produced if the benefactor for the entity you passed into the function is not itself, i.e., it's the parent folder, or another entity in the parent tree.

TYPE: bool DEFAULT: True

overwrite

By default this function overwrites existing permissions for the specified user. Set this flag to False to add new permissions non-destructively.

TYPE: bool DEFAULT: True

synapse_client

If not passed in and caching was not disabled by Synapse.allow_client_caching(False) this will use the last created instance from the Synapse class constructor.

TYPE: Optional[Synapse] DEFAULT: None

RETURNS DESCRIPTION
Dict[str, Union[str, list]]

An Access Control List object

Setting permissions

Grant all registered users download access

from synapseclient import Synapse
from synapseclient.models import File

syn = Synapse()
syn.login()

File(id="syn123").set_permissions(principal_id=273948, access_type=['READ','DOWNLOAD'])

Grant the public view access

from synapseclient import Synapse
from synapseclient.models import File

syn = Synapse()
syn.login()

File(id="syn123").set_permissions(principal_id=273949, access_type=['READ'])
Source code in synapseclient/models/protocols/access_control_protocol.py
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
def set_permissions(
    self,
    principal_id: int = None,
    access_type: List[str] = None,
    modify_benefactor: bool = False,
    warn_if_inherits: bool = True,
    overwrite: bool = True,
    *,
    synapse_client: Optional[Synapse] = None,
) -> Dict[str, Union[str, list]]:
    """
    Sets permission that a user or group has on an Entity.
    An Entity may have its own ACL or inherit its ACL from a benefactor.

    Arguments:
        principal_id: Identifier of a user or group. `273948` is for all
            registered Synapse users and `273949` is for public access.
            None implies public access.
        access_type: Type of permission to be granted. One or more of CREATE,
            READ, DOWNLOAD, UPDATE, DELETE, CHANGE_PERMISSIONS.

            **Defaults to ['READ', 'DOWNLOAD']**
        modify_benefactor: Set as True when modifying a benefactor's ACL. The term
            'benefactor' is used to indicate which Entity an Entity inherits its
            ACL from. For example, a newly created Project will be its own
            benefactor, while a new FileEntity's benefactor will start off as its
            containing Project. If the entity already has local sharing settings
            the benefactor would be itself. It may also be the immediate parent,
            somewhere in the parent tree, or the project itself.
        warn_if_inherits: When `modify_benefactor` is True, this does not have any
            effect. When `modify_benefactor` is False, and `warn_if_inherits` is
            True, a warning log message is produced if the benefactor for the
            entity you passed into the function is not itself, i.e., it's the
            parent folder, or another entity in the parent tree.
        overwrite: By default this function overwrites existing permissions for
            the specified user. Set this flag to False to add new permissions
            non-destructively.
        synapse_client: If not passed in and caching was not disabled by
            `Synapse.allow_client_caching(False)` this will use the last created
            instance from the Synapse class constructor.

    Returns:
        An Access Control List object

    Example: Setting permissions
        Grant all registered users download access

        ```python
        from synapseclient import Synapse
        from synapseclient.models import File

        syn = Synapse()
        syn.login()

        File(id="syn123").set_permissions(principal_id=273948, access_type=['READ','DOWNLOAD'])
        ```

        Grant the public view access

        ```python
        from synapseclient import Synapse
        from synapseclient.models import File

        syn = Synapse()
        syn.login()

        File(id="syn123").set_permissions(principal_id=273949, access_type=['READ'])
        ```
    """
    return {}

delete_permissions

delete_permissions(include_self: bool = True, include_container_content: bool = False, recursive: bool = False, target_entity_types: Optional[List[str]] = None, dry_run: bool = False, show_acl_details: bool = True, show_files_in_containers: bool = True, *, benefactor_tracker: Optional[BenefactorTracker] = None, synapse_client: Optional[Synapse] = None) -> None

Delete the entire Access Control List (ACL) for a given Entity. This is not scoped to a specific user or group, but rather removes all permissions associated with the Entity. After this operation, the Entity will inherit permissions from its benefactor, which is typically its parent entity or the Project it belongs to.

In order to remove permissions for a specific user or group, you should use the set_permissions method with the access_type set to an empty list.

By default, Entities such as FileEntity and Folder inherit their permission from their containing Project. For such Entities the Project is the Entity's 'benefactor'. This permission inheritance can be overridden by creating an ACL for the Entity. When this occurs the Entity becomes its own benefactor and all permission are determined by its own ACL.

If the ACL of an Entity is deleted, then its benefactor will automatically be set to its parent's benefactor.

Special notice for Projects: The ACL for a Project cannot be deleted, you must individually update or revoke the permissions for each user or group.

PARAMETER DESCRIPTION
include_self

If True (default), delete the ACL of the current entity. If False, skip deleting the ACL of the current entity.

TYPE: bool DEFAULT: True

include_container_content

If True, delete ACLs from contents directly within containers (files and folders inside self). This must be set to True for recursive to have any effect. Defaults to False.

TYPE: bool DEFAULT: False

recursive

If True and the entity is a container (e.g., Project or Folder), recursively process child containers. Note that this must be used with include_container_content=True to have any effect. Setting recursive=True with include_container_content=False will raise a ValueError. Only works on classes that support the sync_from_synapse_async method.

TYPE: bool DEFAULT: False

target_entity_types

Specify which entity types to process when deleting ACLs. Allowed values are "folder" and "file" (case-insensitive). If None, defaults to ["folder", "file"]. This does not affect the entity type of the current entity, which is always processed if include_self=True.

TYPE: Optional[List[str]] DEFAULT: None

dry_run

If True, log the changes that would be made instead of actually performing the deletions. When enabled, all ACL deletion operations are simulated and logged at info level. Defaults to False.

TYPE: bool DEFAULT: False

show_acl_details

When dry_run=True, controls whether current ACL details are displayed for entities that will have their permissions changed. If True (default), shows detailed ACL information. If False, hides ACL details for cleaner output. Has no effect when dry_run=False.

TYPE: bool DEFAULT: True

show_files_in_containers

When dry_run=True, controls whether files within containers are displayed in the preview. If True (default), shows all files. If False, hides files when their only change is benefactor inheritance (but still shows files with local ACLs being deleted). Has no effect when dry_run=False.

TYPE: bool DEFAULT: True

benefactor_tracker

Optional tracker for managing benefactor relationships. Used for recursive functionality to track which entities will be affected

TYPE: Optional[BenefactorTracker] DEFAULT: None

synapse_client

If not passed in and caching was not disabled by Synapse.allow_client_caching(False) this will use the last created instance from the Synapse class constructor.

TYPE: Optional[Synapse] DEFAULT: None

RETURNS DESCRIPTION
None

None

RAISES DESCRIPTION
ValueError

If the entity does not have an ID or if an invalid entity type is provided.

SynapseHTTPError

If there are permission issues or if the entity already inherits permissions.

Exception

For any other errors that may occur during the process.

Note: The caller must be granted ACCESS_TYPE.CHANGE_PERMISSIONS on the Entity to call this method.

Delete permissions for a single entity
from synapseclient import Synapse
from synapseclient.models import File

syn = Synapse()
syn.login()

File(id="syn123").delete_permissions()
Delete permissions recursively for a folder and all its children
from synapseclient import Synapse
from synapseclient.models import Folder

syn = Synapse()
syn.login()

# Delete permissions for this folder only (does not affect children)
Folder(id="syn123").delete_permissions()

# Delete permissions for all files and folders directly within this folder,
# but not the folder itself
Folder(id="syn123").delete_permissions(
    include_self=False,
    include_container_content=True
)

# Delete permissions for all items in the entire hierarchy (folders and their files)
# Both recursive and include_container_content must be True
Folder(id="syn123").delete_permissions(
    recursive=True,
    include_container_content=True
)

# Delete permissions only for folder entities within this folder recursively
# and their contents
Folder(id="syn123").delete_permissions(
    recursive=True,
    include_container_content=True,
    target_entity_types=["folder"]
)

# Delete permissions only for files within this folder and all subfolders
Folder(id="syn123").delete_permissions(
    include_self=False,
    recursive=True,
    include_container_content=True,
    target_entity_types=["file"]
)

# Dry run example: Log what would be deleted without making changes
Folder(id="syn123").delete_permissions(
    recursive=True,
    include_container_content=True,
    dry_run=True
)
Source code in synapseclient/models/protocols/access_control_protocol.py
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
def delete_permissions(
    self,
    include_self: bool = True,
    include_container_content: bool = False,
    recursive: bool = False,
    target_entity_types: Optional[List[str]] = None,
    dry_run: bool = False,
    show_acl_details: bool = True,
    show_files_in_containers: bool = True,
    *,
    benefactor_tracker: Optional["BenefactorTracker"] = None,
    synapse_client: Optional[Synapse] = None,
) -> None:
    """
    Delete the entire Access Control List (ACL) for a given Entity. This is not
    scoped to a specific user or group, but rather removes all permissions
    associated with the Entity. After this operation, the Entity will inherit
    permissions from its benefactor, which is typically its parent entity or
    the Project it belongs to.

    In order to remove permissions for a specific user or group, you
    should use the `set_permissions` method with the `access_type` set to
    an empty list.

    By default, Entities such as FileEntity and Folder inherit their permission from
    their containing Project. For such Entities the Project is the Entity's 'benefactor'.
    This permission inheritance can be overridden by creating an ACL for the Entity.
    When this occurs the Entity becomes its own benefactor and all permission are
    determined by its own ACL.

    If the ACL of an Entity is deleted, then its benefactor will automatically be set
    to its parent's benefactor.

    **Special notice for Projects:** The ACL for a Project cannot be deleted, you
    must individually update or revoke the permissions for each user or group.

    Arguments:
        include_self: If True (default), delete the ACL of the current entity.
            If False, skip deleting the ACL of the current entity.
        include_container_content: If True, delete ACLs from contents directly within
            containers (files and folders inside self). This must be set to
            True for recursive to have any effect. Defaults to False.
        recursive: If True and the entity is a container (e.g., Project or Folder),
            recursively process child containers. Note that this must be used with
            include_container_content=True to have any effect. Setting recursive=True
            with include_container_content=False will raise a ValueError.
            Only works on classes that support the `sync_from_synapse_async` method.
        target_entity_types: Specify which entity types to process when deleting ACLs.
            Allowed values are "folder" and "file" (case-insensitive).
            If None, defaults to ["folder", "file"]. This does not affect the
            entity type of the current entity, which is always processed if
            `include_self=True`.
        dry_run: If True, log the changes that would be made instead of actually
            performing the deletions. When enabled, all ACL deletion operations are
            simulated and logged at info level. Defaults to False.
        show_acl_details: When dry_run=True, controls whether current ACL details are
            displayed for entities that will have their permissions changed. If True (default),
            shows detailed ACL information. If False, hides ACL details for cleaner output.
            Has no effect when dry_run=False.
        show_files_in_containers: When dry_run=True, controls whether files within containers
            are displayed in the preview. If True (default), shows all files. If False, hides
            files when their only change is benefactor inheritance (but still shows files with
            local ACLs being deleted). Has no effect when dry_run=False.
        benefactor_tracker: Optional tracker for managing benefactor relationships.
            Used for recursive functionality to track which entities will be affected
        synapse_client: If not passed in and caching was not disabled by
            `Synapse.allow_client_caching(False)` this will use the last created
            instance from the Synapse class constructor.

    Returns:
        None

    Raises:
        ValueError: If the entity does not have an ID or if an invalid entity type is provided.
        SynapseHTTPError: If there are permission issues or if the entity already inherits permissions.
        Exception: For any other errors that may occur during the process.

    Note: The caller must be granted ACCESS_TYPE.CHANGE_PERMISSIONS on the Entity to
    call this method.

    Example: Delete permissions for a single entity
        ```python
        from synapseclient import Synapse
        from synapseclient.models import File

        syn = Synapse()
        syn.login()

        File(id="syn123").delete_permissions()

        ```

    Example: Delete permissions recursively for a folder and all its children
        ```python
        from synapseclient import Synapse
        from synapseclient.models import Folder

        syn = Synapse()
        syn.login()

        # Delete permissions for this folder only (does not affect children)
        Folder(id="syn123").delete_permissions()

        # Delete permissions for all files and folders directly within this folder,
        # but not the folder itself
        Folder(id="syn123").delete_permissions(
            include_self=False,
            include_container_content=True
        )

        # Delete permissions for all items in the entire hierarchy (folders and their files)
        # Both recursive and include_container_content must be True
        Folder(id="syn123").delete_permissions(
            recursive=True,
            include_container_content=True
        )

        # Delete permissions only for folder entities within this folder recursively
        # and their contents
        Folder(id="syn123").delete_permissions(
            recursive=True,
            include_container_content=True,
            target_entity_types=["folder"]
        )

        # Delete permissions only for files within this folder and all subfolders
        Folder(id="syn123").delete_permissions(
            include_self=False,
            recursive=True,
            include_container_content=True,
            target_entity_types=["file"]
        )

        # Dry run example: Log what would be deleted without making changes
        Folder(id="syn123").delete_permissions(
            recursive=True,
            include_container_content=True,
            dry_run=True
        )
        ```
    """
    return None

bind_schema

bind_schema(json_schema_uri: str, *, enable_derived_annotations: Optional[bool] = False, synapse_client: Optional[Synapse] = None) -> JSONSchemaBinding

Bind a JSON schema to the entity.

PARAMETER DESCRIPTION
json_schema_uri

The URI of the JSON schema to bind to the entity.

TYPE: str

enable_derived_annotations

If true, enable derived annotations. Defaults to False.

TYPE: Optional[bool] DEFAULT: False

synapse_client

The Synapse client instance. If not provided, the last created instance from the Synapse class constructor will be used.

TYPE: Optional[Synapse] DEFAULT: None

RETURNS DESCRIPTION
JSONSchemaBinding

An object containing details about the JSON schema binding.

Using this function

Binding JSON schema to a folder or a file. This example expects that you have a Synapse project to use, and a file to upload. Set the PROJECT_NAME and FILE_PATH variables to your project name and file path respectively.

from synapseclient import Synapse
from synapseclient.models import File, Folder

syn = Synapse()
syn.login()

# Define Project and JSON schema info
PROJECT_NAME = "test_json_schema_project"  # replace with your project name
FILE_PATH = "~/Sample.txt"  # replace with your test file path

PROJECT_ID = syn.findEntityId(name=PROJECT_NAME)
ORG_NAME = "UniqueOrg"  # replace with your organization name
SCHEMA_NAME = "myTestSchema"  # replace with your schema name
FOLDER_NAME = "test_script_folder"
VERSION = "0.0.1"
SCHEMA_URI = f"{ORG_NAME}-{SCHEMA_NAME}-{VERSION}"

# Create organization (if not already created)
js = syn.service("json_schema")
all_orgs = js.list_organizations()
for org in all_orgs:
    if org["name"] == ORG_NAME:
        print(f"Organization {ORG_NAME} already exists: {org}")
        break
else:
    print(f"Creating organization {ORG_NAME}.")
    created_organization = js.create_organization(ORG_NAME)
    print(f"Created organization: {created_organization}")


my_test_org = js.JsonSchemaOrganization(ORG_NAME)
test_schema = my_test_org.get_json_schema(SCHEMA_NAME)

if not test_schema:
    # Create the schema (if not already created)
    schema_definition = {
        "$id": "mySchema",
        "type": "object",
        "properties": {
            "foo": {"type": "string"},
            "bar": {"type": "integer"},
        },
        "required": ["foo"]
    }
    test_schema = my_test_org.create_json_schema(schema_definition, SCHEMA_NAME, VERSION)

# Create a test folder
test_folder = Folder(name=FOLDER_NAME, parent_id=PROJECT_ID)
test_folder.store()

# Bind JSON schema to the folder
bound_schema = test_folder.bind_schema(
    json_schema_uri=SCHEMA_URI,
    enable_derived_annotations=True
)
print(f"Result from binding schema to folder: {bound_schema}")

# Bind the same schema to a file
example_file = File(
    path=FILE_PATH,  # Replace with your test file path
    parent_id=test_folder.id,
).store()

bound_schema_file = example_file.bind_schema(
    json_schema_uri=SCHEMA_URI,
    enable_derived_annotations=True
)
print(f"Result from binding schema to file: {bound_schema_file}")
Source code in synapseclient/models/protocols/json_schema_protocol.py
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
def bind_schema(
    self,
    json_schema_uri: str,
    *,
    enable_derived_annotations: Optional[bool] = False,
    synapse_client: Optional["Synapse"] = None,
) -> "JSONSchemaBinding":
    """
    Bind a JSON schema to the entity.

    Arguments:
        json_schema_uri: The URI of the JSON schema to bind to the entity.
        enable_derived_annotations: If true, enable derived annotations. Defaults to False.
        synapse_client: The Synapse client instance. If not provided,
            the last created instance from the Synapse class constructor will be used.

    Returns:
        An object containing details about the JSON schema binding.

    Example: Using this function
        Binding JSON schema to a folder or a file. This example expects that you
        have a Synapse project to use, and a file to upload. Set the `PROJECT_NAME`
        and `FILE_PATH` variables to your project name and file path respectively.

        ```python
        from synapseclient import Synapse
        from synapseclient.models import File, Folder

        syn = Synapse()
        syn.login()

        # Define Project and JSON schema info
        PROJECT_NAME = "test_json_schema_project"  # replace with your project name
        FILE_PATH = "~/Sample.txt"  # replace with your test file path

        PROJECT_ID = syn.findEntityId(name=PROJECT_NAME)
        ORG_NAME = "UniqueOrg"  # replace with your organization name
        SCHEMA_NAME = "myTestSchema"  # replace with your schema name
        FOLDER_NAME = "test_script_folder"
        VERSION = "0.0.1"
        SCHEMA_URI = f"{ORG_NAME}-{SCHEMA_NAME}-{VERSION}"

        # Create organization (if not already created)
        js = syn.service("json_schema")
        all_orgs = js.list_organizations()
        for org in all_orgs:
            if org["name"] == ORG_NAME:
                print(f"Organization {ORG_NAME} already exists: {org}")
                break
        else:
            print(f"Creating organization {ORG_NAME}.")
            created_organization = js.create_organization(ORG_NAME)
            print(f"Created organization: {created_organization}")


        my_test_org = js.JsonSchemaOrganization(ORG_NAME)
        test_schema = my_test_org.get_json_schema(SCHEMA_NAME)

        if not test_schema:
            # Create the schema (if not already created)
            schema_definition = {
                "$id": "mySchema",
                "type": "object",
                "properties": {
                    "foo": {"type": "string"},
                    "bar": {"type": "integer"},
                },
                "required": ["foo"]
            }
            test_schema = my_test_org.create_json_schema(schema_definition, SCHEMA_NAME, VERSION)

        # Create a test folder
        test_folder = Folder(name=FOLDER_NAME, parent_id=PROJECT_ID)
        test_folder.store()

        # Bind JSON schema to the folder
        bound_schema = test_folder.bind_schema(
            json_schema_uri=SCHEMA_URI,
            enable_derived_annotations=True
        )
        print(f"Result from binding schema to folder: {bound_schema}")

        # Bind the same schema to a file
        example_file = File(
            path=FILE_PATH,  # Replace with your test file path
            parent_id=test_folder.id,
        ).store()

        bound_schema_file = example_file.bind_schema(
            json_schema_uri=SCHEMA_URI,
            enable_derived_annotations=True
        )
        print(f"Result from binding schema to file: {bound_schema_file}")
        ```
    """
    return JSONSchemaBinding()

get_schema

get_schema(*, synapse_client: Optional[Synapse] = None) -> JSONSchemaBinding

Get the JSON schema bound to the entity.

PARAMETER DESCRIPTION
synapse_client

The Synapse client instance. If not provided, the last created instance from the Synapse class constructor will be used.

TYPE: Optional[Synapse] DEFAULT: None

RETURNS DESCRIPTION
JSONSchemaBinding

An object containing details about the bound JSON schema.

Using this function

Retrieving the bound JSON schema from a folder or file. This example demonstrates how to get existing schema bindings from entities that already have schemas bound. Set the PROJECT_NAME variable to your project name.

from synapseclient import Synapse
from synapseclient.models import File, Folder

syn = Synapse()
syn.login()

# Define Project and JSON schema info
PROJECT_NAME = "test_json_schema_project"  # replace with your project name
FILE_PATH = "~/Sample.txt"  # replace with your test file path

PROJECT_ID = syn.findEntityId(name=PROJECT_NAME)
ORG_NAME = "UniqueOrg"  # replace with your organization name
SCHEMA_NAME = "myTestSchema"  # replace with your schema name
FOLDER_NAME = "test_script_folder"
VERSION = "0.0.1"
SCHEMA_URI = f"{ORG_NAME}-{SCHEMA_NAME}-{VERSION}"

# Create organization (if not already created)
js = syn.service("json_schema")
all_orgs = js.list_organizations()
for org in all_orgs:
    if org["name"] == ORG_NAME:
        print(f"Organization {ORG_NAME} already exists: {org}")
        break
else:
    print(f"Creating organization {ORG_NAME}.")
    created_organization = js.create_organization(ORG_NAME)
    print(f"Created organization: {created_organization}")

my_test_org = js.JsonSchemaOrganization(ORG_NAME)
test_schema = my_test_org.get_json_schema(SCHEMA_NAME)

if not test_schema:
    # Create the schema (if not already created)
    schema_definition = {
        "$id": "mySchema",
        "type": "object",
        "properties": {
            "foo": {"type": "string"},
            "bar": {"type": "integer"},
        },
        "required": ["foo"]
    }
    test_schema = my_test_org.create_json_schema(schema_definition, SCHEMA_NAME, VERSION)
    print(f"Created new schema: {SCHEMA_NAME}")

# Create a test folder
test_folder = Folder(name=FOLDER_NAME, parent_id=PROJECT_ID)
test_folder.store()
print(f"Created test folder: {FOLDER_NAME}")

# Bind JSON schema to the folder first
bound_schema = test_folder.bind_schema(
    json_schema_uri=SCHEMA_URI,
    enable_derived_annotations=True
)
print(f"Bound schema to folder: {bound_schema}")

# Create and bind schema to a file
example_file = File(
    path=FILE_PATH,  # Replace with your test file path
    parent_id=test_folder.id,
).store()

bound_schema_file = example_file.bind_schema(
    json_schema_uri=SCHEMA_URI,
    enable_derived_annotations=True
)
print(f"Bound schema to file: {bound_schema_file}")

# Retrieve the bound schema from the folder
retrieved_folder_schema = test_folder.get_schema()
print(f"Retrieved schema from folder: {retrieved_folder_schema}")

# Retrieve the bound schema from the file
retrieved_file_schema = example_file.get_schema()
print(f"Retrieved schema from file: {retrieved_file_schema}")
Source code in synapseclient/models/protocols/json_schema_protocol.py
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
def get_schema(
    self, *, synapse_client: Optional["Synapse"] = None
) -> "JSONSchemaBinding":
    """
    Get the JSON schema bound to the entity.

    Arguments:
        synapse_client: The Synapse client instance. If not provided,
            the last created instance from the Synapse class constructor will be used.

    Returns:
        An object containing details about the bound JSON schema.

    Example: Using this function
        Retrieving the bound JSON schema from a folder or file. This example demonstrates
        how to get existing schema bindings from entities that already have schemas bound.
        Set the `PROJECT_NAME` variable to your project name.

        ```python
        from synapseclient import Synapse
        from synapseclient.models import File, Folder

        syn = Synapse()
        syn.login()

        # Define Project and JSON schema info
        PROJECT_NAME = "test_json_schema_project"  # replace with your project name
        FILE_PATH = "~/Sample.txt"  # replace with your test file path

        PROJECT_ID = syn.findEntityId(name=PROJECT_NAME)
        ORG_NAME = "UniqueOrg"  # replace with your organization name
        SCHEMA_NAME = "myTestSchema"  # replace with your schema name
        FOLDER_NAME = "test_script_folder"
        VERSION = "0.0.1"
        SCHEMA_URI = f"{ORG_NAME}-{SCHEMA_NAME}-{VERSION}"

        # Create organization (if not already created)
        js = syn.service("json_schema")
        all_orgs = js.list_organizations()
        for org in all_orgs:
            if org["name"] == ORG_NAME:
                print(f"Organization {ORG_NAME} already exists: {org}")
                break
        else:
            print(f"Creating organization {ORG_NAME}.")
            created_organization = js.create_organization(ORG_NAME)
            print(f"Created organization: {created_organization}")

        my_test_org = js.JsonSchemaOrganization(ORG_NAME)
        test_schema = my_test_org.get_json_schema(SCHEMA_NAME)

        if not test_schema:
            # Create the schema (if not already created)
            schema_definition = {
                "$id": "mySchema",
                "type": "object",
                "properties": {
                    "foo": {"type": "string"},
                    "bar": {"type": "integer"},
                },
                "required": ["foo"]
            }
            test_schema = my_test_org.create_json_schema(schema_definition, SCHEMA_NAME, VERSION)
            print(f"Created new schema: {SCHEMA_NAME}")

        # Create a test folder
        test_folder = Folder(name=FOLDER_NAME, parent_id=PROJECT_ID)
        test_folder.store()
        print(f"Created test folder: {FOLDER_NAME}")

        # Bind JSON schema to the folder first
        bound_schema = test_folder.bind_schema(
            json_schema_uri=SCHEMA_URI,
            enable_derived_annotations=True
        )
        print(f"Bound schema to folder: {bound_schema}")

        # Create and bind schema to a file
        example_file = File(
            path=FILE_PATH,  # Replace with your test file path
            parent_id=test_folder.id,
        ).store()

        bound_schema_file = example_file.bind_schema(
            json_schema_uri=SCHEMA_URI,
            enable_derived_annotations=True
        )
        print(f"Bound schema to file: {bound_schema_file}")

        # Retrieve the bound schema from the folder
        retrieved_folder_schema = test_folder.get_schema()
        print(f"Retrieved schema from folder: {retrieved_folder_schema}")

        # Retrieve the bound schema from the file
        retrieved_file_schema = example_file.get_schema()
        print(f"Retrieved schema from file: {retrieved_file_schema}")
        ```
    """
    return JSONSchemaBinding()

unbind_schema

unbind_schema(*, synapse_client: Optional[Synapse] = None) -> None

Unbind the JSON schema from the entity.

PARAMETER DESCRIPTION
synapse_client

The Synapse client instance. If not provided, the last created instance from the Synapse class constructor will be used.

TYPE: Optional[Synapse] DEFAULT: None

Using this function

Unbinding a JSON schema from a folder or file. This example demonstrates how to remove schema bindings from entities. Assumes entities already have schemas bound. Set the PROJECT_NAME variable to your project name.

from synapseclient import Synapse
from synapseclient.models import File, Folder

syn = Synapse()
syn.login()

# Define Project and JSON schema info
PROJECT_NAME = "test_json_schema_project"  # replace with your project name
FILE_PATH = "~/Sample.txt"  # replace with your test file path

PROJECT_ID = syn.findEntityId(name=PROJECT_NAME)
ORG_NAME = "UniqueOrg"  # replace with your organization name
SCHEMA_NAME = "myTestSchema"  # replace with your schema name
FOLDER_NAME = "test_script_folder"
VERSION = "0.0.1"
SCHEMA_URI = f"{ORG_NAME}-{SCHEMA_NAME}-{VERSION}"

# Create organization (if not already created)
js = syn.service("json_schema")
all_orgs = js.list_organizations()
for org in all_orgs:
    if org["name"] == ORG_NAME:
        print(f"Organization {ORG_NAME} already exists: {org}")
        break
else:
    print(f"Creating organization {ORG_NAME}.")
    created_organization = js.create_organization(ORG_NAME)
    print(f"Created organization: {created_organization}")

my_test_org = js.JsonSchemaOrganization(ORG_NAME)
test_schema = my_test_org.get_json_schema(SCHEMA_NAME)

if not test_schema:
    # Create the schema (if not already created)
    schema_definition = {
        "$id": "mySchema",
        "type": "object",
        "properties": {
            "foo": {"type": "string"},
            "bar": {"type": "integer"},
        },
        "required": ["foo"]
    }
    test_schema = my_test_org.create_json_schema(schema_definition, SCHEMA_NAME, VERSION)
    print(f"Created new schema: {SCHEMA_NAME}")

# Create a test folder
test_folder = Folder(name=FOLDER_NAME, parent_id=PROJECT_ID)
test_folder.store()
print(f"Created test folder: {FOLDER_NAME}")

# Bind JSON schema to the folder first
bound_schema = test_folder.bind_schema(
    json_schema_uri=SCHEMA_URI,
    enable_derived_annotations=True
)
print(f"Bound schema to folder: {bound_schema}")

# Create and bind schema to a file
example_file = File(
    path=FILE_PATH,  # Replace with your test file path
    parent_id=test_folder.id,
).store()

bound_schema_file = example_file.bind_schema(
    json_schema_uri=SCHEMA_URI,
    enable_derived_annotations=True
)
print(f"Bound schema to file: {bound_schema_file}")

# Unbind the schema from the folder
test_folder.unbind_schema()
print("Successfully unbound schema from folder")

# Unbind the schema from the file
example_file.unbind_schema()
print("Successfully unbound schema from file")
Source code in synapseclient/models/protocols/json_schema_protocol.py
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
def unbind_schema(self, *, synapse_client: Optional["Synapse"] = None) -> None:
    """
    Unbind the JSON schema from the entity.

    Arguments:
        synapse_client: The Synapse client instance. If not provided,
            the last created instance from the Synapse class constructor will be used.

    Example: Using this function
        Unbinding a JSON schema from a folder or file. This example demonstrates
        how to remove schema bindings from entities. Assumes entities already have
        schemas bound. Set the `PROJECT_NAME` variable to your project name.

        ```python
        from synapseclient import Synapse
        from synapseclient.models import File, Folder

        syn = Synapse()
        syn.login()

        # Define Project and JSON schema info
        PROJECT_NAME = "test_json_schema_project"  # replace with your project name
        FILE_PATH = "~/Sample.txt"  # replace with your test file path

        PROJECT_ID = syn.findEntityId(name=PROJECT_NAME)
        ORG_NAME = "UniqueOrg"  # replace with your organization name
        SCHEMA_NAME = "myTestSchema"  # replace with your schema name
        FOLDER_NAME = "test_script_folder"
        VERSION = "0.0.1"
        SCHEMA_URI = f"{ORG_NAME}-{SCHEMA_NAME}-{VERSION}"

        # Create organization (if not already created)
        js = syn.service("json_schema")
        all_orgs = js.list_organizations()
        for org in all_orgs:
            if org["name"] == ORG_NAME:
                print(f"Organization {ORG_NAME} already exists: {org}")
                break
        else:
            print(f"Creating organization {ORG_NAME}.")
            created_organization = js.create_organization(ORG_NAME)
            print(f"Created organization: {created_organization}")

        my_test_org = js.JsonSchemaOrganization(ORG_NAME)
        test_schema = my_test_org.get_json_schema(SCHEMA_NAME)

        if not test_schema:
            # Create the schema (if not already created)
            schema_definition = {
                "$id": "mySchema",
                "type": "object",
                "properties": {
                    "foo": {"type": "string"},
                    "bar": {"type": "integer"},
                },
                "required": ["foo"]
            }
            test_schema = my_test_org.create_json_schema(schema_definition, SCHEMA_NAME, VERSION)
            print(f"Created new schema: {SCHEMA_NAME}")

        # Create a test folder
        test_folder = Folder(name=FOLDER_NAME, parent_id=PROJECT_ID)
        test_folder.store()
        print(f"Created test folder: {FOLDER_NAME}")

        # Bind JSON schema to the folder first
        bound_schema = test_folder.bind_schema(
            json_schema_uri=SCHEMA_URI,
            enable_derived_annotations=True
        )
        print(f"Bound schema to folder: {bound_schema}")

        # Create and bind schema to a file
        example_file = File(
            path=FILE_PATH,  # Replace with your test file path
            parent_id=test_folder.id,
        ).store()

        bound_schema_file = example_file.bind_schema(
            json_schema_uri=SCHEMA_URI,
            enable_derived_annotations=True
        )
        print(f"Bound schema to file: {bound_schema_file}")

        # Unbind the schema from the folder
        test_folder.unbind_schema()
        print("Successfully unbound schema from folder")

        # Unbind the schema from the file
        example_file.unbind_schema()
        print("Successfully unbound schema from file")
        ```
    """

validate_schema

validate_schema(*, synapse_client: Optional[Synapse] = None) -> Union[JSONSchemaValidation, InvalidJSONSchemaValidation]

Validate the entity against the bound JSON schema.

PARAMETER DESCRIPTION
synapse_client

The Synapse client instance. If not provided, the last created instance from the Synapse class constructor will be used.

TYPE: Optional[Synapse] DEFAULT: None

RETURNS DESCRIPTION
Union[JSONSchemaValidation, InvalidJSONSchemaValidation]

The validation results.

Using this function

Validating a folder or file against the bound JSON schema. This example demonstrates how to validate entities with annotations against their bound schemas. Requires entities to have schemas already bound. Set the PROJECT_NAME variable to your project name.

from synapseclient import Synapse
from synapseclient.models import File, Folder
import time

syn = Synapse()
syn.login()

# Define Project and JSON schema info
PROJECT_NAME = "test_json_schema_project"  # replace with your project name
FILE_PATH = "~/Sample.txt"  # replace with your test file path

PROJECT_ID = syn.findEntityId(name=PROJECT_NAME)
ORG_NAME = "UniqueOrg"  # replace with your organization name
SCHEMA_NAME = "myTestSchema"  # replace with your schema name
FOLDER_NAME = "test_script_folder"
VERSION = "0.0.1"
SCHEMA_URI = f"{ORG_NAME}-{SCHEMA_NAME}-{VERSION}"

# Create organization (if not already created)
js = syn.service("json_schema")
all_orgs = js.list_organizations()
for org in all_orgs:
    if org["name"] == ORG_NAME:
        print(f"Organization {ORG_NAME} already exists: {org}")
        break
else:
    print(f"Creating organization {ORG_NAME}.")
    created_organization = js.create_organization(ORG_NAME)
    print(f"Created organization: {created_organization}")

my_test_org = js.JsonSchemaOrganization(ORG_NAME)
test_schema = my_test_org.get_json_schema(SCHEMA_NAME)

if not test_schema:
    # Create the schema (if not already created)
    schema_definition = {
        "$id": "mySchema",
        "type": "object",
        "properties": {
            "foo": {"type": "string"},
            "bar": {"type": "integer"},
        },
        "required": ["foo"]
    }
    test_schema = my_test_org.create_json_schema(schema_definition, SCHEMA_NAME, VERSION)
    print(f"Created new schema: {SCHEMA_NAME}")

# Create a test folder
test_folder = Folder(name=FOLDER_NAME, parent_id=PROJECT_ID)
test_folder.store()
print(f"Created test folder: {FOLDER_NAME}")

# Bind JSON schema to the folder
bound_schema = test_folder.bind_schema(
    json_schema_uri=SCHEMA_URI,
    enable_derived_annotations=True
)
print(f"Bound schema to folder: {bound_schema}")

# Create and bind schema to a file
example_file = File(
    path=FILE_PATH,  # Replace with your test file path
    parent_id=test_folder.id,
).store()

bound_schema_file = example_file.bind_schema(
    json_schema_uri=SCHEMA_URI,
    enable_derived_annotations=True
)
print(f"Bound schema to file: {bound_schema_file}")

# Validate the folder entity against the bound schema
test_folder.annotations = {"foo": "test_value", "bar": 42}  # Example annotations
test_folder.store()
print("Added annotations to folder and stored")
time.sleep(2)  # Allow time for processing

validation_response = test_folder.validate_schema()
print(f"Folder validation response: {validation_response}")

# Validate the file entity against the bound schema
example_file.annotations = {"foo": "test_value", "bar": 43}  # Example annotations
example_file.store()
print("Added annotations to file and stored")
time.sleep(2)  # Allow time for processing

validation_response_file = example_file.validate_schema()
print(f"File validation response: {validation_response_file}")
Source code in synapseclient/models/protocols/json_schema_protocol.py
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
def validate_schema(
    self, *, synapse_client: Optional["Synapse"] = None
) -> Union["JSONSchemaValidation", "InvalidJSONSchemaValidation"]:
    """
    Validate the entity against the bound JSON schema.

    Arguments:
        synapse_client: The Synapse client instance. If not provided,
            the last created instance from the Synapse class constructor will be used.

    Returns:
        The validation results.

    Example: Using this function
        Validating a folder or file against the bound JSON schema. This example demonstrates
        how to validate entities with annotations against their bound schemas. Requires entities
        to have schemas already bound. Set the `PROJECT_NAME` variable to your project name.

        ```python
        from synapseclient import Synapse
        from synapseclient.models import File, Folder
        import time

        syn = Synapse()
        syn.login()

        # Define Project and JSON schema info
        PROJECT_NAME = "test_json_schema_project"  # replace with your project name
        FILE_PATH = "~/Sample.txt"  # replace with your test file path

        PROJECT_ID = syn.findEntityId(name=PROJECT_NAME)
        ORG_NAME = "UniqueOrg"  # replace with your organization name
        SCHEMA_NAME = "myTestSchema"  # replace with your schema name
        FOLDER_NAME = "test_script_folder"
        VERSION = "0.0.1"
        SCHEMA_URI = f"{ORG_NAME}-{SCHEMA_NAME}-{VERSION}"

        # Create organization (if not already created)
        js = syn.service("json_schema")
        all_orgs = js.list_organizations()
        for org in all_orgs:
            if org["name"] == ORG_NAME:
                print(f"Organization {ORG_NAME} already exists: {org}")
                break
        else:
            print(f"Creating organization {ORG_NAME}.")
            created_organization = js.create_organization(ORG_NAME)
            print(f"Created organization: {created_organization}")

        my_test_org = js.JsonSchemaOrganization(ORG_NAME)
        test_schema = my_test_org.get_json_schema(SCHEMA_NAME)

        if not test_schema:
            # Create the schema (if not already created)
            schema_definition = {
                "$id": "mySchema",
                "type": "object",
                "properties": {
                    "foo": {"type": "string"},
                    "bar": {"type": "integer"},
                },
                "required": ["foo"]
            }
            test_schema = my_test_org.create_json_schema(schema_definition, SCHEMA_NAME, VERSION)
            print(f"Created new schema: {SCHEMA_NAME}")

        # Create a test folder
        test_folder = Folder(name=FOLDER_NAME, parent_id=PROJECT_ID)
        test_folder.store()
        print(f"Created test folder: {FOLDER_NAME}")

        # Bind JSON schema to the folder
        bound_schema = test_folder.bind_schema(
            json_schema_uri=SCHEMA_URI,
            enable_derived_annotations=True
        )
        print(f"Bound schema to folder: {bound_schema}")

        # Create and bind schema to a file
        example_file = File(
            path=FILE_PATH,  # Replace with your test file path
            parent_id=test_folder.id,
        ).store()

        bound_schema_file = example_file.bind_schema(
            json_schema_uri=SCHEMA_URI,
            enable_derived_annotations=True
        )
        print(f"Bound schema to file: {bound_schema_file}")

        # Validate the folder entity against the bound schema
        test_folder.annotations = {"foo": "test_value", "bar": 42}  # Example annotations
        test_folder.store()
        print("Added annotations to folder and stored")
        time.sleep(2)  # Allow time for processing

        validation_response = test_folder.validate_schema()
        print(f"Folder validation response: {validation_response}")

        # Validate the file entity against the bound schema
        example_file.annotations = {"foo": "test_value", "bar": 43}  # Example annotations
        example_file.store()
        print("Added annotations to file and stored")
        time.sleep(2)  # Allow time for processing

        validation_response_file = example_file.validate_schema()
        print(f"File validation response: {validation_response_file}")
        ```
    """
    return InvalidJSONSchemaValidation() or JSONSchemaValidation()

get_schema_derived_keys

get_schema_derived_keys(*, synapse_client: Optional[Synapse] = None) -> JSONSchemaDerivedKeys

Retrieve derived JSON schema keys for the entity.

PARAMETER DESCRIPTION
synapse_client

The Synapse client instance. If not provided, the last created instance from the Synapse class constructor will be used.

TYPE: Optional[Synapse] DEFAULT: None

RETURNS DESCRIPTION
JSONSchemaDerivedKeys

An object containing the derived keys for the entity.

Using this function

Retrieving derived keys from a folder or file. This example demonstrates how to get derived annotation keys from schemas with constant values. Set the PROJECT_NAME variable to your project name.

from synapseclient import Synapse
from synapseclient.models import File, Folder

syn = Synapse()
syn.login()

# Define Project and JSON schema info
PROJECT_NAME = "test_json_schema_project"  # replace with your project name
FILE_PATH = "~/Sample.txt"  # replace with your test file path

PROJECT_ID = syn.findEntityId(name=PROJECT_NAME)
ORG_NAME = "UniqueOrg"  # replace with your organization name
DERIVED_TEST_SCHEMA_NAME = "myTestDerivedSchema"  # replace with your derived schema name
FOLDER_NAME = "test_script_folder"
VERSION = "0.0.1"
SCHEMA_URI = f"{ORG_NAME}-{DERIVED_TEST_SCHEMA_NAME}-{VERSION}"

# Create organization (if not already created)
js = syn.service("json_schema")
all_orgs = js.list_organizations()
for org in all_orgs:
    if org["name"] == ORG_NAME:
        print(f"Organization {ORG_NAME} already exists: {org}")
        break
else:
    print(f"Creating organization {ORG_NAME}.")
    created_organization = js.create_organization(ORG_NAME)
    print(f"Created organization: {created_organization}")

my_test_org = js.JsonSchemaOrganization(ORG_NAME)
test_schema = my_test_org.get_json_schema(DERIVED_TEST_SCHEMA_NAME)

if not test_schema:
    # Create the schema (if not already created)
    schema_definition = {
        "$id": "mySchema",
        "type": "object",
        "properties": {
            "foo": {"type": "string"},
            "baz": {"type": "string", "const": "example_value"},  # Example constant for derived annotation
            "bar": {"type": "integer"},
        },
        "required": ["foo"]
    }
    test_schema = my_test_org.create_json_schema(schema_definition, DERIVED_TEST_SCHEMA_NAME, VERSION)
    print(f"Created new derived schema: {DERIVED_TEST_SCHEMA_NAME}")

# Create a test folder
test_folder = Folder(name=FOLDER_NAME, parent_id=PROJECT_ID)
test_folder.store()
print(f"Created test folder: {FOLDER_NAME}")

# Bind JSON schema to the folder
bound_schema = test_folder.bind_schema(
    json_schema_uri=SCHEMA_URI,
    enable_derived_annotations=True
)
print(f"Bound schema to folder with derived annotations: {bound_schema}")

# Create and bind schema to a file
example_file = File(
    path=FILE_PATH,  # Replace with your test file path
    parent_id=test_folder.id,
).store()

bound_schema_file = example_file.bind_schema(
    json_schema_uri=SCHEMA_URI,
    enable_derived_annotations=True
)
print(f"Bound schema to file with derived annotations: {bound_schema_file}")

# Get the derived keys from the bound schema of the folder
test_folder.annotations = {"foo": "test_value_new", "bar": 42}  # Example annotations
test_folder.store()
print("Added annotations to folder and stored")

derived_keys = test_folder.get_schema_derived_keys()
print(f"Derived keys from folder: {derived_keys}")

# Get the derived keys from the bound schema of the file
example_file.annotations = {"foo": "test_value_new", "bar": 43}  # Example annotations
example_file.store()
print("Added annotations to file and stored")

derived_keys_file = example_file.get_schema_derived_keys()
print(f"Derived keys from file: {derived_keys_file}")
Source code in synapseclient/models/protocols/json_schema_protocol.py
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
def get_schema_derived_keys(
    self, *, synapse_client: Optional["Synapse"] = None
) -> "JSONSchemaDerivedKeys":
    """
    Retrieve derived JSON schema keys for the entity.

    Arguments:
        synapse_client: The Synapse client instance. If not provided,
            the last created instance from the Synapse class constructor will be used.

    Returns:
        An object containing the derived keys for the entity.

    Example: Using this function
        Retrieving derived keys from a folder or file. This example demonstrates
        how to get derived annotation keys from schemas with constant values.
        Set the `PROJECT_NAME` variable to your project name.

        ```python
        from synapseclient import Synapse
        from synapseclient.models import File, Folder

        syn = Synapse()
        syn.login()

        # Define Project and JSON schema info
        PROJECT_NAME = "test_json_schema_project"  # replace with your project name
        FILE_PATH = "~/Sample.txt"  # replace with your test file path

        PROJECT_ID = syn.findEntityId(name=PROJECT_NAME)
        ORG_NAME = "UniqueOrg"  # replace with your organization name
        DERIVED_TEST_SCHEMA_NAME = "myTestDerivedSchema"  # replace with your derived schema name
        FOLDER_NAME = "test_script_folder"
        VERSION = "0.0.1"
        SCHEMA_URI = f"{ORG_NAME}-{DERIVED_TEST_SCHEMA_NAME}-{VERSION}"

        # Create organization (if not already created)
        js = syn.service("json_schema")
        all_orgs = js.list_organizations()
        for org in all_orgs:
            if org["name"] == ORG_NAME:
                print(f"Organization {ORG_NAME} already exists: {org}")
                break
        else:
            print(f"Creating organization {ORG_NAME}.")
            created_organization = js.create_organization(ORG_NAME)
            print(f"Created organization: {created_organization}")

        my_test_org = js.JsonSchemaOrganization(ORG_NAME)
        test_schema = my_test_org.get_json_schema(DERIVED_TEST_SCHEMA_NAME)

        if not test_schema:
            # Create the schema (if not already created)
            schema_definition = {
                "$id": "mySchema",
                "type": "object",
                "properties": {
                    "foo": {"type": "string"},
                    "baz": {"type": "string", "const": "example_value"},  # Example constant for derived annotation
                    "bar": {"type": "integer"},
                },
                "required": ["foo"]
            }
            test_schema = my_test_org.create_json_schema(schema_definition, DERIVED_TEST_SCHEMA_NAME, VERSION)
            print(f"Created new derived schema: {DERIVED_TEST_SCHEMA_NAME}")

        # Create a test folder
        test_folder = Folder(name=FOLDER_NAME, parent_id=PROJECT_ID)
        test_folder.store()
        print(f"Created test folder: {FOLDER_NAME}")

        # Bind JSON schema to the folder
        bound_schema = test_folder.bind_schema(
            json_schema_uri=SCHEMA_URI,
            enable_derived_annotations=True
        )
        print(f"Bound schema to folder with derived annotations: {bound_schema}")

        # Create and bind schema to a file
        example_file = File(
            path=FILE_PATH,  # Replace with your test file path
            parent_id=test_folder.id,
        ).store()

        bound_schema_file = example_file.bind_schema(
            json_schema_uri=SCHEMA_URI,
            enable_derived_annotations=True
        )
        print(f"Bound schema to file with derived annotations: {bound_schema_file}")

        # Get the derived keys from the bound schema of the folder
        test_folder.annotations = {"foo": "test_value_new", "bar": 42}  # Example annotations
        test_folder.store()
        print("Added annotations to folder and stored")

        derived_keys = test_folder.get_schema_derived_keys()
        print(f"Derived keys from folder: {derived_keys}")

        # Get the derived keys from the bound schema of the file
        example_file.annotations = {"foo": "test_value_new", "bar": 43}  # Example annotations
        example_file.store()
        print("Added annotations to file and stored")

        derived_keys_file = example_file.get_schema_derived_keys()
        print(f"Derived keys from file: {derived_keys_file}")
        ```
    """
    return JSONSchemaDerivedKeys()

get_schema_validation_statistics

get_schema_validation_statistics(*, synapse_client: Optional[Synapse] = None) -> JSONSchemaValidationStatistics

Get validation statistics for a container entity.

PARAMETER DESCRIPTION
synapse_client

The Synapse client instance. If not provided, the last created instance from the Synapse class constructor will be used.

TYPE: Optional[Synapse] DEFAULT: None

RETURNS DESCRIPTION
JSONSchemaValidationStatistics

The validation statistics.

Using this function

Retrieving validation statistics for a folder. This example demonstrates how to get validation statistics for a container entity after creating entities with various validation states. Set the PROJECT_NAME variable to your project name.

from synapseclient import Synapse
from synapseclient.models import File, Folder
import time

syn = Synapse()
syn.login()

# Define Project and JSON schema info
PROJECT_NAME = "test_json_schema_project"  # replace with your project name
FILE_PATH = "~/Sample.txt"  # replace with your test file path

PROJECT_ID = syn.findEntityId(name=PROJECT_NAME)
ORG_NAME = "UniqueOrg"  # replace with your organization name
SCHEMA_NAME = "myTestSchema"  # replace with your schema name
FOLDER_NAME = "test_script_folder"
VERSION = "0.0.1"
SCHEMA_URI = f"{ORG_NAME}-{SCHEMA_NAME}-{VERSION}"

# Create organization (if not already created)
js = syn.service("json_schema")
all_orgs = js.list_organizations()
for org in all_orgs:
    if org["name"] == ORG_NAME:
        print(f"Organization {ORG_NAME} already exists: {org}")
        break
else:
    print(f"Creating organization {ORG_NAME}.")
    created_organization = js.create_organization(ORG_NAME)
    print(f"Created organization: {created_organization}")

my_test_org = js.JsonSchemaOrganization(ORG_NAME)
test_schema = my_test_org.get_json_schema(SCHEMA_NAME)

if not test_schema:
    # Create the schema (if not already created)
    schema_definition = {
        "$id": "mySchema",
        "type": "object",
        "properties": {
            "foo": {"type": "string"},
            "baz": {"type": "string", "const": "example_value"},
            "bar": {"type": "integer"},
        },
        "required": ["foo"]
    }
    test_schema = my_test_org.create_json_schema(schema_definition, SCHEMA_NAME, VERSION)
    print(f"Created new schema: {SCHEMA_NAME}")

# Create a test folder
test_folder = Folder(name=FOLDER_NAME, parent_id=PROJECT_ID)
test_folder.store()
print(f"Created test folder: {FOLDER_NAME}")

# Bind JSON schema to the folder
bound_schema = test_folder.bind_schema(
    json_schema_uri=SCHEMA_URI,
    enable_derived_annotations=True
)
print(f"Bound schema to folder: {bound_schema}")

# Create files within the folder with invalid annotations to generate statistics
invalid_file1 = File(
    path=FILE_PATH,  # assumes you have something here or adjust path
    parent_id=test_folder.id
)
invalid_file1.annotations = {"foo": 123, "bar": "not_an_integer"}  # both invalid
invalid_file1.store()
print("Created file with invalid annotations")
time.sleep(2)  # Allow time for processing

# Get schema validation statistics
stats = test_folder.get_schema_validation_statistics()
print(f"Validation statistics: {stats}")
Source code in synapseclient/models/protocols/json_schema_protocol.py
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
def get_schema_validation_statistics(
    self, *, synapse_client: Optional["Synapse"] = None
) -> "JSONSchemaValidationStatistics":
    """
    Get validation statistics for a container entity.

    Arguments:
        synapse_client: The Synapse client instance. If not provided,
            the last created instance from the Synapse class constructor will be used.

    Returns:
        The validation statistics.

    Example: Using this function
        Retrieving validation statistics for a folder. This example demonstrates
        how to get validation statistics for a container entity after creating
        entities with various validation states. Set the `PROJECT_NAME` variable to your project name.

        ```python
        from synapseclient import Synapse
        from synapseclient.models import File, Folder
        import time

        syn = Synapse()
        syn.login()

        # Define Project and JSON schema info
        PROJECT_NAME = "test_json_schema_project"  # replace with your project name
        FILE_PATH = "~/Sample.txt"  # replace with your test file path

        PROJECT_ID = syn.findEntityId(name=PROJECT_NAME)
        ORG_NAME = "UniqueOrg"  # replace with your organization name
        SCHEMA_NAME = "myTestSchema"  # replace with your schema name
        FOLDER_NAME = "test_script_folder"
        VERSION = "0.0.1"
        SCHEMA_URI = f"{ORG_NAME}-{SCHEMA_NAME}-{VERSION}"

        # Create organization (if not already created)
        js = syn.service("json_schema")
        all_orgs = js.list_organizations()
        for org in all_orgs:
            if org["name"] == ORG_NAME:
                print(f"Organization {ORG_NAME} already exists: {org}")
                break
        else:
            print(f"Creating organization {ORG_NAME}.")
            created_organization = js.create_organization(ORG_NAME)
            print(f"Created organization: {created_organization}")

        my_test_org = js.JsonSchemaOrganization(ORG_NAME)
        test_schema = my_test_org.get_json_schema(SCHEMA_NAME)

        if not test_schema:
            # Create the schema (if not already created)
            schema_definition = {
                "$id": "mySchema",
                "type": "object",
                "properties": {
                    "foo": {"type": "string"},
                    "baz": {"type": "string", "const": "example_value"},
                    "bar": {"type": "integer"},
                },
                "required": ["foo"]
            }
            test_schema = my_test_org.create_json_schema(schema_definition, SCHEMA_NAME, VERSION)
            print(f"Created new schema: {SCHEMA_NAME}")

        # Create a test folder
        test_folder = Folder(name=FOLDER_NAME, parent_id=PROJECT_ID)
        test_folder.store()
        print(f"Created test folder: {FOLDER_NAME}")

        # Bind JSON schema to the folder
        bound_schema = test_folder.bind_schema(
            json_schema_uri=SCHEMA_URI,
            enable_derived_annotations=True
        )
        print(f"Bound schema to folder: {bound_schema}")

        # Create files within the folder with invalid annotations to generate statistics
        invalid_file1 = File(
            path=FILE_PATH,  # assumes you have something here or adjust path
            parent_id=test_folder.id
        )
        invalid_file1.annotations = {"foo": 123, "bar": "not_an_integer"}  # both invalid
        invalid_file1.store()
        print("Created file with invalid annotations")
        time.sleep(2)  # Allow time for processing

        # Get schema validation statistics
        stats = test_folder.get_schema_validation_statistics()
        print(f"Validation statistics: {stats}")
        ```
    """
    return JSONSchemaValidationStatistics()

get_invalid_validation

get_invalid_validation(*, synapse_client: Optional[Synapse] = None) -> Generator[InvalidJSONSchemaValidation, None, None]

Get invalid JSON schema validation results for a container entity.

PARAMETER DESCRIPTION
synapse_client

The Synapse client instance. If not provided, the last created instance from the Synapse class constructor will be used.

TYPE: Optional[Synapse] DEFAULT: None

YIELDS DESCRIPTION
InvalidJSONSchemaValidation

An object containing the validation response, all validation messages, and the validation exception details.

Using this function

Retrieving invalid validation results for a folder. This example demonstrates how to get detailed invalid validation results for child entities within a container. Set the PROJECT_NAME variable to your project name.

import time
from synapseclient import Synapse
from synapseclient.models import File, Folder

syn = Synapse()
syn.login()

# Define Project and JSON schema info
PROJECT_NAME = "test_json_schema_project"  # replace with your project name
FILE_PATH = "~/Sample.txt"  # replace with your test file path

PROJECT_ID = syn.findEntityId(name=PROJECT_NAME)
ORG_NAME = "UniqueOrg"  # replace with your organization name
SCHEMA_NAME = "myTestSchema"  # replace with your schema name
FOLDER_NAME = "test_script_folder"
VERSION = "0.0.1"
SCHEMA_URI = f"{ORG_NAME}-{SCHEMA_NAME}-{VERSION}"

# Create organization (if not already created)
js = syn.service("json_schema")
all_orgs = js.list_organizations()
for org in all_orgs:
    if org["name"] == ORG_NAME:
        print(f"Organization {ORG_NAME} already exists: {org}")
        break
else:
    print(f"Creating organization {ORG_NAME}.")
    created_organization = js.create_organization(ORG_NAME)
    print(f"Created organization: {created_organization}")

my_test_org = js.JsonSchemaOrganization(ORG_NAME)
test_schema = my_test_org.get_json_schema(SCHEMA_NAME)

if not test_schema:
    # Create the schema (if not already created)
    schema_definition = {
        "$id": "mySchema",
        "type": "object",
        "properties": {
            "foo": {"type": "string"},
            "baz": {"type": "string", "const": "example_value"},
            "bar": {"type": "integer"},
        },
        "required": ["foo"]
    }
    test_schema = my_test_org.create_json_schema(schema_definition, SCHEMA_NAME, VERSION)
    print(f"Created new schema: {SCHEMA_NAME}")

# Create a test folder
test_folder = Folder(name=FOLDER_NAME, parent_id=PROJECT_ID)
test_folder.store()
print(f"Created test folder: {FOLDER_NAME}")

# Bind JSON schema to the folder
bound_schema = test_folder.bind_schema(
    json_schema_uri=SCHEMA_URI,
    enable_derived_annotations=True
)
print(f"Bound schema to folder: {bound_schema}")

# Create files within the folder with invalid annotations to generate invalid results
invalid_file1 = File(
    path=FILE_PATH,  # assumes you have something here or adjust path
    parent_id=test_folder.id
)
invalid_file1.annotations = {"foo": 123, "bar": "not_an_integer"}  # both invalid
invalid_file1.store()
print("Created file with invalid annotations")
time.sleep(2)  # Allow time for processing

# Get invalid validation results
invalid_results = test_folder.get_invalid_validation(synapse_client=syn)
print(f"Invalid validation items found:")
for child in invalid_results:
    print(f"Invalid validation item: {child}")
Source code in synapseclient/models/mixins/json_schema.py
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
def get_invalid_validation(
    self, *, synapse_client: Optional["Synapse"] = None
) -> Generator[InvalidJSONSchemaValidation, None, None]:
    """
    Get invalid JSON schema validation results for a container entity.

    Arguments:
        synapse_client (Optional[Synapse], optional): The Synapse client instance. If not provided,
            the last created instance from the Synapse class constructor will be used.

    Yields:
        An object containing the validation response, all validation messages,
                                     and the validation exception details.

    Example: Using this function
        Retrieving invalid validation results for a folder. This example demonstrates
        how to get detailed invalid validation results for child entities within a container.
        Set the `PROJECT_NAME` variable to your project name.

        ```python
        import time
        from synapseclient import Synapse
        from synapseclient.models import File, Folder

        syn = Synapse()
        syn.login()

        # Define Project and JSON schema info
        PROJECT_NAME = "test_json_schema_project"  # replace with your project name
        FILE_PATH = "~/Sample.txt"  # replace with your test file path

        PROJECT_ID = syn.findEntityId(name=PROJECT_NAME)
        ORG_NAME = "UniqueOrg"  # replace with your organization name
        SCHEMA_NAME = "myTestSchema"  # replace with your schema name
        FOLDER_NAME = "test_script_folder"
        VERSION = "0.0.1"
        SCHEMA_URI = f"{ORG_NAME}-{SCHEMA_NAME}-{VERSION}"

        # Create organization (if not already created)
        js = syn.service("json_schema")
        all_orgs = js.list_organizations()
        for org in all_orgs:
            if org["name"] == ORG_NAME:
                print(f"Organization {ORG_NAME} already exists: {org}")
                break
        else:
            print(f"Creating organization {ORG_NAME}.")
            created_organization = js.create_organization(ORG_NAME)
            print(f"Created organization: {created_organization}")

        my_test_org = js.JsonSchemaOrganization(ORG_NAME)
        test_schema = my_test_org.get_json_schema(SCHEMA_NAME)

        if not test_schema:
            # Create the schema (if not already created)
            schema_definition = {
                "$id": "mySchema",
                "type": "object",
                "properties": {
                    "foo": {"type": "string"},
                    "baz": {"type": "string", "const": "example_value"},
                    "bar": {"type": "integer"},
                },
                "required": ["foo"]
            }
            test_schema = my_test_org.create_json_schema(schema_definition, SCHEMA_NAME, VERSION)
            print(f"Created new schema: {SCHEMA_NAME}")

        # Create a test folder
        test_folder = Folder(name=FOLDER_NAME, parent_id=PROJECT_ID)
        test_folder.store()
        print(f"Created test folder: {FOLDER_NAME}")

        # Bind JSON schema to the folder
        bound_schema = test_folder.bind_schema(
            json_schema_uri=SCHEMA_URI,
            enable_derived_annotations=True
        )
        print(f"Bound schema to folder: {bound_schema}")

        # Create files within the folder with invalid annotations to generate invalid results
        invalid_file1 = File(
            path=FILE_PATH,  # assumes you have something here or adjust path
            parent_id=test_folder.id
        )
        invalid_file1.annotations = {"foo": 123, "bar": "not_an_integer"}  # both invalid
        invalid_file1.store()
        print("Created file with invalid annotations")
        time.sleep(2)  # Allow time for processing

        # Get invalid validation results
        invalid_results = test_folder.get_invalid_validation(synapse_client=syn)
        print(f"Invalid validation items found:")
        for child in invalid_results:
            print(f"Invalid validation item: {child}")
        ```
    """
    gen = get_invalid_json_schema_validation_sync(
        synapse_client=synapse_client, synapse_id=self.id
    )

    for item in gen:
        yield InvalidJSONSchemaValidation(
            validation_response=JSONSchemaValidation(
                object_id=item.get("objectId", None),
                object_type=item.get("objectType", None),
                object_etag=item.get("objectEtag", None),
                id=item.get("schema$id", None),
                is_valid=item.get("isValid", None),
                validated_on=item.get("validatedOn", None),
            ),
            validation_error_message=item.get("validationErrorMessage", None),
            all_validation_messages=item.get("allValidationMessages", []),
            validation_exception=ValidationException(
                pointer_to_violation=item.get("validationException", {}).get(
                    "pointerToViolation", None
                ),
                message=item.get("validationException", {}).get("message", None),
                schema_location=item.get("validationException", {}).get(
                    "schemaLocation", None
                ),
                causing_exceptions=[
                    CausingException(
                        keyword=ce.get("keyword", None),
                        pointer_to_violation=ce.get("pointerToViolation", None),
                        message=ce.get("message", None),
                        schema_location=ce.get("schemaLocation", None),
                        causing_exceptions=[
                            CausingException(
                                keyword=nce.get("keyword", None),
                                pointer_to_violation=nce.get(
                                    "pointerToViolation", None
                                ),
                                message=nce.get("message", None),
                                schema_location=nce.get("schemaLocation", None),
                            )
                            for nce in ce.get("causingExceptions", [])
                        ],
                    )
                    for ce in item.get("validationException", {}).get(
                        "causingExceptions", []
                    )
                ],
            ),
        )