Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ALE parser causes AttributeError: SerializableCollection / Clip object has no attribute 'tracks' #1687

Open
tomviner opened this issue Jan 5, 2024 · 0 comments
Labels
bug A problem, flaw, or broken functionality.

Comments

@tomviner
Copy link

tomviner commented Jan 5, 2024

Bug Report

Broken Functionality

Parts of the codebase assume the existence of a tracks attribute. However, ALE inputs don't have this. This is because the ALE adapter doesn't follow the "Canonical Structure" with a Timeline containing tracks which contain clips. Instead it uses a SerializableCollection containing clips directly.

To Reproduce

otiostat outputs an error for every sample ALE file:

$ otiostat ./contrib/opentimelineio_contrib/adapters/tests/sample_data/*.ale
parsed: True
top level object: SerializableCollection.1
number of tracks: 0
There was a system error: 'opentimelineio._otio.SerializableCollection' object has no attribute 'tracks'
...

otioconvert also attempts to access a tracks attribute on the SerializableCollection:

$ otioconvert -i ./contrib/opentimelineio_contrib/adapters/tests/sample_data/sample.ale -o out.edl
Traceback (most recent call last):
  File "/Users/myuser/.virtualenvs/opentimeline-gh/bin/otioconvert", line 8, in <module>
    sys.exit(main())
  File "/Users/myuser/dev/OpenTimelineIO/src/py-opentimelineio/opentimelineio/console/otioconvert.py", line 273, in main
    otio.adapters.write_to_file(
  File "/Users/myuser/dev/OpenTimelineIO/src/py-opentimelineio/opentimelineio/adapters/__init__.py", line 192, in write_to_file
    return adapter.write_to_file(
  File "/Users/myuser/dev/OpenTimelineIO/src/py-opentimelineio/opentimelineio/adapters/adapter.py", line 183, in write_to_file
    result = self.write_to_string(input_otio, **adapter_argument_map)
  File "/Users/myuser/dev/OpenTimelineIO/src/py-opentimelineio/opentimelineio/adapters/adapter.py", line 274, in write_to_string
    return self._execute_function(
  File "/Users/myuser/dev/OpenTimelineIO/src/py-opentimelineio/opentimelineio/plugins/python_plugin.py", line 142, in _execute_function
    return (getattr(self.module(), func_name)(**kwargs))
  File "/Users/myuser/dev/OpenTimelineIO/src/py-opentimelineio/opentimelineio/adapters/cmx_3600.py", line 800, in write_to_string
    video_tracks = [t for t in input_otio.tracks
AttributeError: 'opentimelineio._otio.SerializableCollection' object has no attribute 'tracks'

otioview attempts to access a tracks attribute on the Clip, when you click an item in the sidebar:

image
$ otioview ./contrib/opentimelineio_contrib/adapters/tests/sample_data/sampleUHD.ale
Traceback (most recent call last):
  File "/Users/myuser/dev/OpenTimelineIO/src/opentimelineview/console.py", line 214, in _change_track
    self.timeline_widget.set_timeline(selection[0].timeline)
  File "/Users/myuser/dev/OpenTimelineIO/src/opentimelineview/timeline_widget.py", line 785, in set_timeline
    self.add_stack(timeline.tracks)
AttributeError: 'opentimelineio._otio.Clip' object has no attribute 'tracks'

Expected Behavior

Adapters should not create data structures that other parts of the library don't know how to handle.

I'm not familiar enough with this library or why the ale adapter was created this way, to know the correct solution. Here are the two options I see:

1. Handle differences and catch errors

The tracebacks above should be inspected and we attempt to proceed as best as possible given the different schemas used. Simple to catch the error in otiostat, but for otioview and otioconvert we may have to add special case code or error with a friendly message explaining this command isn't available with this datatype.

2. Convert to using Canonical Structure

Amend the ALE adapter to create objects in the canonical format. Perhaps behind a flag, for backwards compatibility?
I've amended a few lines, just to test the feasibility of this. See main...tomviner:OpenTimelineIO:ale-adapter-attrib-errors It's totally incomplete, but it does enable the commands to function:

otiostat

Before

$ otiostat ./contrib/opentimelineio_contrib/adapters/tests/sample_data/sample.ale
parsed: True
top level object: SerializableCollection.1
number of tracks: 0
There was a system error: 'opentimelineio._otio.SerializableCollection' object has no attribute 'tracks'
deepest nesting: 1
number of clips: 4
total duration: n/a
total duration in timecode: n/a
top level rate: n/a
clips with cdl data: 0
Tracks with non standard types: 0

With patch

$ otiostat ./contrib/opentimelineio_contrib/adapters/tests/sample_data/sample.ale
parsed: True
top level object: Timeline.1
number of tracks: 1
Tracks are the same length: True
deepest nesting: 4
number of clips: 4
total duration: RationalTime(402, 24)
total duration in timecode: 00:00:16:18
top level rate: 24.0
clips with cdl data: 0
Tracks with non standard types: 0

Diff

Note the error message, which is actually sent to stderr, is fixed. And note the duration is now filled in.

-There was a system error: 'opentimelineio._otio.SerializableCollection' object has no attribute 'tracks'
 parsed: True
-top level object: SerializableCollection.1
-number of tracks: 0
-deepest nesting: 1
+top level object: Timeline.1
+number of tracks: 1
+Tracks are the same length: True
+deepest nesting: 4
 number of clips: 4
-total duration: n/a
-total duration in timecode: n/a
-top level rate: n/a
+total duration: RationalTime(402, 24)
+total duration in timecode: 00:00:16:18
+top level rate: 24.0
 clips with cdl data: 0
 Tracks with non standard types: 0

otioconvert

This now works without an exception. Although round-tripping back to ALE loses a lot of data, as my patch is incomplete.

$ otioconvert -i ./contrib/opentimelineio_contrib/adapters/tests/sample_data/sample.ale -o out.edl

otioview

$ otioview ./contrib/opentimelineio_contrib/adapters/tests/sample_data/sample.ale

There's now no sidebar, just a timeline:

image

Thoughts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A problem, flaw, or broken functionality.
Projects
None yet
Development

No branches or pull requests

1 participant