Entity

The Entity class is the base class for all entities, including Project, Folder and File, Link, as well as deprecated entity types such as Data, Study, Summary, etc.

Entities are dictionary-like objects in which both object and dictionary notation (entity.foo or entity[‘foo’]) can be used interchangeably.

Imports:

from synapseclient import Project, Folder, File, Link
class synapseclient.entity.Entity(properties=None, annotations=None, local_state=None, parent=None, **kwargs)

A Synapse entity is an object that has metadata, access control, and potentially a file. It can represent data, source code, or a folder that contains other entities.

Entities should typically be created using the constructors for specific subclasses such as Project, Folder or File.

Project

class synapseclient.entity.Project(name=None, properties=None, annotations=None, local_state=None, **kwargs)

Represents a project in Synapse.

Projects in Synapse must be uniquely named. Trying to create a project with a name that’s already taken, say ‘My project’, will result in an error

project = Project('Foobarbat project')
project = syn.store(project)

Folder

class synapseclient.entity.Folder(name=None, parent=None, properties=None, annotations=None, local_state=None, **kwargs)

Represents a folder in Synapse.

Folders must have a name and a parent and can optionally have annotations.

folder = Folder('my data', parent=project)
folder = syn.store(Folder)

File

class synapseclient.entity.File(path=None, parent=None, synapseStore=True, properties=None, annotations=None, local_state=None, **kwargs)

Represents a file in Synapse.

When a File object is stored, the associated local file or its URL will be stored in Synapse. A File must have a path (or URL) and a parent.

Parameters:
  • path – Location to be represented by this File
  • name – Name of the file in Synapse, not to be confused with the name within the path
  • parent – Project or Folder where this File is stored
  • synapseStore – Whether the File should be uploaded or if only the path should be stored. Defaults to True (file should be uploaded)
  • contentType – Manually specify Content-type header, for example “application/png” or “application/json; charset=UTF-8”
data = File('/path/to/file/data.xyz', parent=folder)
data = syn.store(data)

Changing File Names

A Synapse File Entity has a name separate from the name of the actual file it represents. When a file is uploaded to Synapse, its filename is fixed, even though the name of the entity can be changed at any time. Synapse provides a way to effectively change the filename by setting a special property called “fileNameOverride”.

Setting the fileNameOverride means that the file will then be downloaded with the new name.:

>>> e = syn.get(synid)
>>> print(os.path.basename(e.path))  ## prints, e.g., "my_file.txt"
>>> e.fileNameOverride = "my_newname_file.txt"
>>> e = syn.store(e)

Setting fileNameOverride will not change the name of a copy of the file that’s already downloaded into your local cache. Either rename the local copy manually or remove it from the cache and re-download.:

>>> syn.cache.remove(e.dataFileHandleId)
>>> e = syn.get(e)
>>> print(os.path.basename(e.path))  ## prints "my_newname_file.txt"

Table Schema

class synapseclient.table.Schema(name=None, columns=None, parent=None, properties=None, annotations=None, local_state=None, **kwargs)

A Schema is a synapse.entity.Entity that defines a set of columns in a table.

Parameters:
  • name – give the Table Schema object a name
  • description
  • columns – a list of Column objects or their IDs
  • parent – the project (file a bug if you’d like folders supported) in Synapse to which this table belongs
cols = [Column(name='Isotope', columnType='STRING'),
        Column(name='Atomic Mass', columnType='INTEGER'),
        Column(name='Halflife', columnType='DOUBLE'),
        Column(name='Discovered', columnType='DATE')]

schema = syn.store(Schema(name='MyTable', columns=cols, parent=project))

Properties and annotations, implementation details

In Synapse, entities have both properties and annotations. Properties are used by the system, whereas annotations are completely user defined. In the Python client, we try to present this situation as a normal object, with one set of properties.

Printing an entity will show the division between properties and annotations.:

print(entity)

Under the covers, an Entity object has two dictionaries, one for properties and one for annotations. These two namespaces are distinct, so there is a possibility of collisions. It is recommended to avoid defining annotations with names that collide with properties, but this is not enforced.:

## don't do this!
entity.properties['description'] = 'One thing'
entity.annotations['description'] = 'A different thing'

In case of conflict, properties will take precedence.:

print(entity.description)
#> One thing

Some additional ambiguity is entailed in the use of dot notation. Entity objects have their own internal properties which are not persisted to Synapse. As in all Python objects, these properties are held in object.__dict__. For example, this dictionary holds the keys ‘properties’ and ‘annotations’ whose values are both dictionaries themselves.

The rule, for either getting or setting is: first look in the object then look in properties, then look in annotations. If the key is not found in any of these three, a get results in a KeyError and a set results in a new annotation being created. Thus, the following results in a new annotation that will be persisted in Synapse:

entity.foo = 'bar'

To create an object member variable, which will not be persisted in Synapse, this unfortunate notation is required:

entity.__dict__['foo'] = 'bar'

As mentioned previously, name collisions are entirely possible. Keys in the three namespaces can be referred to unambiguously like so:

entity.__dict__['key']

entity.properties.key
entity.properties['key']

entity.annotations.key
entity.annotations['key']

Most of the time, users should be able to ignore these distinctions and treat Entities like normal Python objects. End users should never need to manipulate items in __dict__.

See also: