Jump to content

Add and get new component in the same session doesn't work


Remus Avram

Recommended Posts

Hi all,

we need to add and get a component for a AssetVersion in the same session.

Ex:

unmanaged_location = session.query('Location where name is "ftrack.unmanaged"').one()
version = session.query("AssetVersion where id is 87912656-5d89-11e6-a165-005056a76761").first()
path = '/path/to/a/file'
new_com_name = 'test_component'

print len(version['components'])

version.create_component(
                                         path,
                                         data={'name': new_com_name},
                                         location=unmanaged_location
                         )
session.commit()

print len(version['components'])

Result:

1

1

Only if we reopen the session we can get the new component.

Cheers!

Link to comment
Share on other sites

Hi,

The result of version['components'] is cached and will not be re-fetched from the server the second time you print the amount of components in the version.

To address the issue, you can add the component to the collection manually:

component = version.create_component(...)
if component not in version['components']:
    version['components'].append(component)

I'll look into if we should do this automatically within in the create_component helper method.

Regards,
Lucas

Link to comment
Share on other sites

Hmm, I think I misunderstood the situation somewhat.

You should be able to "refetch" a version's components by querying it again. For example:

version = session.query(
    'select components from AssetVersion where id is "{}"'.format(
        version['id']
    )
).one()

However, there seems to be a bug which is preventing this from working properly. I've added a ticket which we'll take a look at soon.

Regards,
Lucas

Link to comment
Share on other sites

TLDR; You should be able to also do:

del version["components"]
session.populate(version, "components")

This is most likely to do with how collection references are currently managed in the API and the way Python works.

Behind every attribute are actually two data stores: local and remote

Remote holds values fetched from the server, whilst local is intended to track local uncommitted changes (which can be discarded client side without committing).

For simple scalar attributes this works well:

>>> user = session.query("User").first()
>>> print user.attributes.get("username")
<ftrack_api.attribute.ScalarAttribute(username) object at 63763984>
>>> print user.attributes.get("username").get_remote_value(user)
NOT_SET
>>> print user.attributes.get("username").get_local_value(user)
NOT_SET
>>> print user["username"] # Populates remote value from server as not set.
anthonyf
>>> print user.attributes.get("username").get_remote_value(user)
anthonyf
>>> print user.attributes.get("username").get_local_value(user)
NOT_SET
>>> user["username"] = "martinpp"  # Sets local value only. 
>>> print user.attributes.get("username").get_remote_value(user)
anthonyf
>>> print user.attributes.get("username").get_local_value(user)
martinpp
>>> print user["username"]  # Uses local value.
martinpp
>>> del user["username"]  # Odd syntax, but clears local value only.
>>> print user.attributes.get("username").get_remote_value(user)
anthonyf
>>> print user.attributes.get("username").get_local_value(user)
NOT_SET
>>> print user["username"]  # Uses remote value (does not refetch from server).
anthonyf

However, for Collections (list like structures in Python), the local value has to be populated whenever the remote is, so that you can modify the list at all (list.append etc). This is because remote values are always immutable.

>>> print user.attributes.get("timelogs")
<ftrack_api.attribute.CollectionAttribute(timelogs) object at 60467472>
>>> print user.attributes.get("timelogs").get_local_value(user)
NOT_SET
>>> print user.attributes.get("timelogs").get_remote_value(user)
NOT_SET
>>> print user["timelogs"]  # Fetches and populates remote value from server, but also populates the local value for modification.
<ftrack_api.collection.Collection object at 0x3b21610>
>>> print user.attributes.get("timelogs").get_local_value(user)
<ftrack_api.collection.Collection object at 0x3b21610>
>>> print user.attributes.get("timelogs").get_remote_value(user)
<ftrack_api.collection.Collection object at 0x3b24d50>

This means that you will always see the local value (even when you didn't modify it) unless you explicitly clear it and let it repopulate from the remote value on next access. If you have an updated server value to fetch you should be able to do the following which is less heavy handed than session.reset:

del user["timelogs"]
session.populate(user, "timelogs")

@ftrack-support - Might be worth adding something like this to the documentation for clarity (until the issue resolved).

ps. How do you get Python syntax highlighting in this forum? I can't see an option...

Link to comment
Share on other sites

  • 1 month later...
  • 4 months later...

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...