+from pprint import pformat
+from ftrack_api import Session
+import opentimelineio as otio
+EDL_FILE_PATH = './myedit.edl'
+ "working_duration": None
+def ftrack_ensure_fields(session):
+ # ENSURE ALL THE NEEDED CATORIES AND CUSTOM ATTRIBUTES ARE IN PLACE.
+ session.ensure('ListCategory', {'name': 'Cut'})
+ custom_attribute_text_type = session.query(
+ 'CustomAttributeType where name is "text"'
+ security_roles = session.query('SecurityRole').all()
+ attribute_group = session.ensure(
+ 'CustomAttributeGroup',
+ {'name': 'Cut Information'})
+ 'CustomAttributeConfiguration where key is asset_version_id'
+ session.create('CustomAttributeConfiguration', {
+ 'entity_type': 'listobject',
+ 'type': custom_attribute_text_type,
+ 'key': 'asset_version_id',
+ 'config': json.dumps({'markdown': False}),
+ 'write_security_roles': security_roles,
+ 'read_security_roles': security_roles
+ 'CustomAttributeConfiguration where key is cut_version'
+ session.create('CustomAttributeConfiguration', {
+ 'type': custom_attribute_text_type,
+ 'label': 'Cut version',
+ 'config': json.dumps({'markdown': False}),
+ 'write_security_roles': security_roles,
+ 'read_security_roles': security_roles
+ clip_attributes = base_clip_data.keys()
+ for attribute in clip_attributes:
+ clip_attribute_name = attribute.replace('_', ' ').capitalize()
+ 'CustomAttributeConfiguration where key is {}'.format(attribute)
+ session.create('CustomAttributeConfiguration', {
+ 'entity_type': 'listobject',
+ 'type': custom_attribute_text_type,
+ 'label': clip_attribute_name,
+ 'config': json.dumps({'markdown': False}),
+ 'group': attribute_group,
+ 'write_security_roles': security_roles,
+ 'read_security_roles': security_roles
+def extract_data(edl_path, session, project):
+ # fetch asset type to link to
+ asset_type = session.query('AssetType').first()
+ version_status = session.query('Status').first()
+ # fetch the list category Cut
+ list_category = session.query('ListCategory where name is Cut').one()
+ # get information from the project so we can create shots...
+ project_schema = project['project_schema']
+ default_shot_status = project_schema.get_statuses('Shot')[0]
+ # Ensure a new list is available in the cuts
+ new_cut = session.ensure(
+ 'category_id': list_category['id'],
+ 'project_id': project['id']
+ new_cut['custom_attributes']['cut_version'] = '1'
+ timeline = otio.adapters.read_from_file(edl_path)
+ for track in timeline.video_tracks():
+ clip_data = base_clip_data.copy()
+ item_name = item.name.split('.')[0]
+ # Create shot and assets
+ 'Shot where name is "{}" and parent.id is "{}" and status.id is "{}"'.format(
+ item_name, project['id'], default_shot_status['id']
+ 'status': default_shot_status
+ 'Asset where name is "{}" and parent.id is "{}" and type.id is "{}"'.format(
+ item_name, shot['id'], asset_type['id']
+ asset = session.create('Asset', {
+ version = session.create('AssetVersion', {
+ 'status': version_status,
+ 'comment': 'auto created...',
+ print asset['context_id']
+ list_object = session.ensure(
+ 'list_id': new_cut['id'],
+ 'entity_id': asset['context_id']
+ list_object['custom_attributes']['asset_version_id'] = version['id']
+ if not isinstance(item, otio.schema.Clip):
+ # handle clip information only
+ clip_range = clip.trimmed_range()
+ cut_in = otio.opentime.to_frames(
+ cut_out = otio.opentime.to_frames(
+ clip_range.end_time_exclusive()
+ cut_duration = otio.opentime.to_frames(
+ edit_range = clip.source_range
+ head_in = otio.opentime.to_frames(
+ tail_out = otio.opentime.to_frames(
+ edit_range.end_time_exclusive()
+ working_duration = otio.opentime.to_frames(
+ clip_data['cut_in'] = cut_in
+ clip_data['cut_out'] = cut_out
+ clip_data['cut_duration'] = cut_duration
+ clip_data['head_in'] = head_in
+ clip_data['tail_out'] = tail_out
+ clip_data['working_duration'] = working_duration
+ for key, value in clip_data.items():
+ list_object['custom_attributes'][key] = value
+ftrack_ensure_fields(session)
+project = session.ensure('Project', {'name': 'edits'})
+extract_data(EDL_FILE_PATH, session, project)
+# proint dict(s.query('ListObject').first()['custom_attributes'])