diff --git a/src/opentimelineio/serializableCollection.h b/src/opentimelineio/serializableCollection.h index 34fd7278f..e65bb8ee1 100644 --- a/src/opentimelineio/serializableCollection.h +++ b/src/opentimelineio/serializableCollection.h @@ -5,6 +5,7 @@ #include "opentimelineio/composition.h" #include "opentimelineio/serializableObjectWithMetadata.h" +#include "opentimelineio/timeline.h" #include "opentimelineio/version.h" namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { @@ -98,8 +99,8 @@ SerializableCollection::children_if( out.push_back(valid_child); } - // if not a shallow_search, for children that are serialiable collections or compositions, - // recurse into their children + // if not a shallow_search, for children that are serializable collections, + // compositions, or timelines, recurse into their children if (!shallow_search) { if (auto collection = @@ -129,6 +130,19 @@ SerializableCollection::children_if( out.push_back(valid_child); } } + else if (auto timeline = dynamic_cast(child.value)) + { + const auto valid_children = + timeline->children_if(error_status, search_range); + if (is_error(error_status)) + { + return out; + } + for (const auto& valid_child: valid_children) + { + out.push_back(valid_child); + } + } } } return out; diff --git a/src/py-opentimelineio/opentimelineio-bindings/otio_serializableObjects.cpp b/src/py-opentimelineio/opentimelineio-bindings/otio_serializableObjects.cpp index 76b496e5a..c52ab4c6c 100644 --- a/src/py-opentimelineio/opentimelineio-bindings/otio_serializableObjects.cpp +++ b/src/py-opentimelineio/opentimelineio-bindings/otio_serializableObjects.cpp @@ -289,12 +289,12 @@ A :class:`~SerializableCollection` is useful for serializing multiple timelines, .def("__iter__", [](SerializableCollection* c) { return new SerializableCollectionIterator(c); }) - .def("clip_if", [](SerializableCollection* t, optional const& search_range) { - return clip_if(t, search_range); - }, "search_range"_a = nullopt) - .def("children_if", [](SerializableCollection* t, py::object descended_from_type, optional const& search_range) { - return children_if(t, descended_from_type, search_range); - }, "descended_from_type"_a = py::none(), "search_range"_a = nullopt); + .def("clip_if", [](SerializableCollection* t, optional const& search_range, bool shallow_search) { + return clip_if(t, search_range, shallow_search); + }, "search_range"_a = nullopt, "shallow_search"_a = false) + .def("children_if", [](SerializableCollection* t, py::object descended_from_type, optional const& search_range, bool shallow_search) { + return children_if(t, descended_from_type, search_range, shallow_search); + }, "descended_from_type"_a = py::none(), "search_range"_a = nullopt, "shallow_search"_a = false); } @@ -611,9 +611,9 @@ Should be subclassed (for example by :class:`.Track` and :class:`.Stack`), not u "markers"_a = py::none(), "effects"_a = py::none(), py::arg_v("metadata"_a = py::none())) - .def("clip_if", [](Stack* t, optional const& search_range) { - return clip_if(t, search_range); - }, "search_range"_a = nullopt); + .def("clip_if", [](Stack* t, optional const& search_range, bool shallow_search) { + return clip_if(t, search_range, shallow_search); + }, "search_range"_a = nullopt, "shallow_search"_a = false); py::class_>(m, "Timeline", py::dynamic_attr()) .def(py::init([](std::string name, @@ -641,12 +641,12 @@ Should be subclassed (for example by :class:`.Track` and :class:`.Stack`), not u }) .def("video_tracks", &Timeline::video_tracks) .def("audio_tracks", &Timeline::audio_tracks) - .def("clip_if", [](Timeline* t, optional const& search_range) { - return clip_if(t, search_range); - }, "search_range"_a = nullopt) - .def("children_if", [](Timeline* t, py::object descended_from_type, optional const& search_range) { - return children_if(t, descended_from_type, search_range); - }, "descended_from_type"_a = py::none(), "search_range"_a = nullopt); + .def("clip_if", [](Timeline* t, optional const& search_range, bool shallow_search) { + return clip_if(t, search_range, shallow_search); + }, "search_range"_a = nullopt, "shallow_search"_a = false) + .def("children_if", [](Timeline* t, py::object descended_from_type, optional const& search_range, bool shallow_search) { + return children_if(t, descended_from_type, search_range, shallow_search); + }, "descended_from_type"_a = py::none(), "search_range"_a = nullopt, "shallow_search"_a = false); } static void define_effects(py::module m) { diff --git a/src/py-opentimelineio/opentimelineio/schema/serializable_collection.py b/src/py-opentimelineio/opentimelineio/schema/serializable_collection.py index 9029484dd..674dfe412 100644 --- a/src/py-opentimelineio/opentimelineio/schema/serializable_collection.py +++ b/src/py-opentimelineio/opentimelineio/schema/serializable_collection.py @@ -31,7 +31,8 @@ def __repr__(self): @add_method(_otio.SerializableCollection) -def each_child(self, search_range=None, descended_from_type=_otio.Composable): +def each_child(self, search_range=None, descended_from_type=_otio.Composable, + shallow_search=False): """ Generator that returns each child contained in the serializable collection in the order in which it is found. @@ -42,13 +43,15 @@ def each_child(self, search_range=None, descended_from_type=_otio.Composable): with the search range will be yielded. :param type descended_from_type: if specified, only children who are a descendent of the descended_from_type will be yielded. + :param bool shallow_search: if True, will only search children of self and not + recurse into children of children. """ - for child in self.children_if(descended_from_type, search_range): + for child in self.children_if(descended_from_type, search_range, shallow_search): yield child @add_method(_otio.SerializableCollection) -def each_clip(self, search_range=None): +def each_clip(self, search_range=None, shallow_search=False): """ Generator that returns each clip contained in the serializable collection in the order in which it is found. @@ -57,6 +60,8 @@ def each_clip(self, search_range=None): :param TimeRange search_range: if specified, only children whose range overlaps with the search range will be yielded. + :param bool shallow_search: if True, will only search children of self and not + recurse into children of children. """ - for child in self.clip_if(search_range): + for child in self.clip_if(search_range, shallow_search): yield child diff --git a/src/py-opentimelineio/opentimelineio/schema/stack.py b/src/py-opentimelineio/opentimelineio/schema/stack.py index 34f56c6e2..5177ea826 100644 --- a/src/py-opentimelineio/opentimelineio/schema/stack.py +++ b/src/py-opentimelineio/opentimelineio/schema/stack.py @@ -6,7 +6,7 @@ @add_method(_otio.Stack) -def each_clip(self, search_range=None): +def each_clip(self, search_range=None, shallow_search=False): """Generator that returns each clip contained in the stack in the order in which it is found. @@ -15,6 +15,8 @@ def each_clip(self, search_range=None): :param TimeRange search_range: if specified, only children whose range overlaps with the search range will be yielded. + :param bool shallow_search: if True, will only search children of self and not + recurse into children of children. """ - for child in self.clip_if(search_range): + for child in self.clip_if(search_range, shallow_search): yield child diff --git a/src/py-opentimelineio/opentimelineio/schema/timeline.py b/src/py-opentimelineio/opentimelineio/schema/timeline.py index ea7682d9e..f8ecf7aba 100644 --- a/src/py-opentimelineio/opentimelineio/schema/timeline.py +++ b/src/py-opentimelineio/opentimelineio/schema/timeline.py @@ -21,7 +21,8 @@ def __repr__(self): @add_method(_otio.Timeline) -def each_child(self, search_range=None, descended_from_type=_otio.Composable): +def each_child(self, search_range=None, descended_from_type=_otio.Composable, + shallow_search=False): """Generator that returns each child contained in the timeline in the order in which it is found. @@ -32,13 +33,15 @@ def each_child(self, search_range=None, descended_from_type=_otio.Composable): with the search range will be yielded. :param type descended_from_type: if specified, only children who are a descendent of the descended_from_type will be yielded. + :param bool shallow_search: if True, will only search children of self and not + recurse into children of children. """ - for child in self.children_if(descended_from_type, search_range): + for child in self.children_if(descended_from_type, search_range, shallow_search): yield child @add_method(_otio.Timeline) -def each_clip(self, search_range=None): +def each_clip(self, search_range=None, shallow_search=False): """Generator that returns each clip contained in the timeline in the order in which it is found. @@ -47,6 +50,8 @@ def each_clip(self, search_range=None): :param TimeRange search_range: if specified, only children whose range overlaps with the search range will be yielded. + :param bool shallow_search: if True, will only search children of self and not + recurse into children of children. """ - for child in self.clip_if(search_range): + for child in self.clip_if(search_range, shallow_search): yield child diff --git a/src/py-opentimelineio/opentimelineio/schema/track.py b/src/py-opentimelineio/opentimelineio/schema/track.py index cd851e495..c98dee2d2 100644 --- a/src/py-opentimelineio/opentimelineio/schema/track.py +++ b/src/py-opentimelineio/opentimelineio/schema/track.py @@ -14,9 +14,9 @@ def each_clip(self, search_range=None, shallow_search=False): Use :meth:`clip_if` instead. :param TimeRange search_range: if specified, only children whose range overlaps with - the search range will be yielded. - :param bool shallow_search: if True, will only search children of self, not - and not recurse into children of children. + the search range will be yielded. + :param bool shallow_search: if True, will only search children of self and not + recurse into children of children. """ - for child in self.clip_if(search_range): + for child in self.clip_if(search_range, shallow_search): yield child diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 02e7b39ba..57a5231c8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -15,7 +15,7 @@ foreach(test ${tests_opentime}) WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) endforeach() -list(APPEND tests_opentimelineio test_clip) +list(APPEND tests_opentimelineio test_clip test_serializableCollection test_timeline test_track) foreach(test ${tests_opentimelineio}) add_executable(${test} utils.h utils.cpp ${test}.cpp) diff --git a/tests/test_clip.cpp b/tests/test_clip.cpp index 68d82432a..8dac199bc 100644 --- a/tests/test_clip.cpp +++ b/tests/test_clip.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include diff --git a/tests/test_serializableCollection.cpp b/tests/test_serializableCollection.cpp new file mode 100644 index 000000000..831ce0c4f --- /dev/null +++ b/tests/test_serializableCollection.cpp @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Contributors to the OpenTimelineIO project + +#include "utils.h" + +#include +#include +#include +#include + +#include + +namespace otime = opentime::OPENTIME_VERSION; +namespace otio = opentimelineio::OPENTIMELINEIO_VERSION; + +int +main(int argc, char** argv) +{ + Tests tests; + + tests.add_test( + "test_children_if", [] { + using namespace otio; + otio::SerializableObject::Retainer cl = + new otio::Clip(); + otio::SerializableObject::Retainer tr = + new otio::Track(); + tr->append_child(cl); + otio::SerializableObject::Retainer tl = + new otio::Timeline(); + tl->tracks()->append_child(tr); + otio::SerializableObject::Retainer + sc = new otio::SerializableCollection(); + sc->insert_child(0, tl); + opentimelineio::v1_0::ErrorStatus err; + auto result = sc->children_if(&err, {}, false); + assertEqual(result.size(), 1); + assertEqual(result[0].value, cl.value); + }); + tests.add_test( + "test_children_if_search_range", [] { + using namespace otio; + const TimeRange range(RationalTime(0.0, 24.0), RationalTime(24.0, 24.0)); + otio::SerializableObject::Retainer cl0 = + new otio::Clip(); + cl0->set_source_range(range); + otio::SerializableObject::Retainer cl1 = + new otio::Clip(); + cl1->set_source_range(range); + otio::SerializableObject::Retainer cl2 = + new otio::Clip(); + cl2->set_source_range(range); + otio::SerializableObject::Retainer tr = + new otio::Track(); + tr->append_child(cl0); + tr->append_child(cl1); + tr->append_child(cl2); + otio::SerializableObject::Retainer tl = + new otio::Timeline(); + tl->tracks()->append_child(tr); + otio::SerializableObject::Retainer + sc = new otio::SerializableCollection(); + sc->insert_child(0, tl); + opentimelineio::v1_0::ErrorStatus err; + auto result = sc->children_if(&err, range); + assertEqual(result.size(), 1); + assertEqual(result[0].value, cl0.value); + }); + tests.add_test( + "test_children_if_shallow_search", [] { + using namespace otio; + otio::SerializableObject::Retainer cl = + new otio::Clip(); + otio::SerializableObject::Retainer tr = + new otio::Track(); + tr->append_child(cl); + otio::SerializableObject::Retainer tl = + new otio::Timeline(); + tl->tracks()->append_child(tr); + otio::SerializableObject::Retainer + sc = new otio::SerializableCollection(); + sc->insert_child(0, tl); + opentimelineio::v1_0::ErrorStatus err; + auto result = sc->children_if(&err, nullopt, true); + assertEqual(result.size(), 0); + result = sc->children_if(&err, nullopt, false); + assertEqual(result.size(), 1); + assertEqual(result[0].value, cl.value); + }); + + tests.run(argc, argv); + return 0; +} diff --git a/tests/test_serializable_collection.py b/tests/test_serializable_collection.py index bb22aa1de..1eafd2085 100644 --- a/tests/test_serializable_collection.py +++ b/tests/test_serializable_collection.py @@ -71,6 +71,54 @@ def test_repr(self): ")" ) + def test_children_if(self): + cl = otio.schema.Clip() + tr = otio.schema.Track() + tr.append(cl) + tl = otio.schema.Timeline() + tl.tracks.append(tr) + sc = otio.schema.SerializableCollection() + sc.append(tl) + result = sc.children_if(otio.schema.Clip) + self.assertEqual(len(result), 1) + self.assertEqual(result[0], cl) + + def test_children_if_search_range(self): + range = otio.opentime.TimeRange( + otio.opentime.RationalTime(0.0, 24.0), + otio.opentime.RationalTime(24.0, 24.0)) + cl0 = otio.schema.Clip() + cl0.source_range = range + cl1 = otio.schema.Clip() + cl1.source_range = range + cl2 = otio.schema.Clip() + cl2.source_range = range + tr = otio.schema.Track() + tr.append(cl0) + tr.append(cl1) + tr.append(cl2) + tl = otio.schema.Timeline() + tl.tracks.append(tr) + sc = otio.schema.SerializableCollection() + sc.append(tl) + result = sc.children_if(otio.schema.Clip, range) + self.assertEqual(len(result), 1) + self.assertEqual(result[0], cl0) + + def test_children_if_shallow_search(self): + cl = otio.schema.Clip() + tr = otio.schema.Track() + tr.append(cl) + tl = otio.schema.Timeline() + tl.tracks.append(tr) + sc = otio.schema.SerializableCollection() + sc.append(tl) + result = sc.children_if(otio.schema.Clip, shallow_search=True) + self.assertEqual(len(result), 0) + result = sc.children_if(otio.schema.Clip, shallow_search=False) + self.assertEqual(len(result), 1) + self.assertEqual(result[0], cl) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_timeline.cpp b/tests/test_timeline.cpp new file mode 100644 index 000000000..ac9970f2e --- /dev/null +++ b/tests/test_timeline.cpp @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Contributors to the OpenTimelineIO project + +#include "utils.h" + +#include +#include +#include + +#include + +namespace otime = opentime::OPENTIME_VERSION; +namespace otio = opentimelineio::OPENTIMELINEIO_VERSION; + +int +main(int argc, char** argv) +{ + Tests tests; + + tests.add_test( + "test_children_if", [] { + using namespace otio; + otio::SerializableObject::Retainer cl = + new otio::Clip(); + otio::SerializableObject::Retainer tr = + new otio::Track(); + tr->append_child(cl); + otio::SerializableObject::Retainer tl = + new otio::Timeline(); + tl->tracks()->append_child(tr); + opentimelineio::v1_0::ErrorStatus err; + auto result = tl->children_if(&err); + assertEqual(result.size(), 1); + assertEqual(result[0].value, cl.value); + }); + tests.add_test( + "test_children_if_search_range", [] { + using namespace otio; + const TimeRange range(RationalTime(0.0, 24.0), RationalTime(24.0, 24.0)); + otio::SerializableObject::Retainer cl0 = + new otio::Clip(); + cl0->set_source_range(range); + otio::SerializableObject::Retainer cl1 = + new otio::Clip(); + cl1->set_source_range(range); + otio::SerializableObject::Retainer cl2 = + new otio::Clip(); + cl2->set_source_range(range); + otio::SerializableObject::Retainer tr = + new otio::Track(); + tr->append_child(cl0); + tr->append_child(cl1); + tr->append_child(cl2); + otio::SerializableObject::Retainer tl = + new otio::Timeline(); + tl->tracks()->append_child(tr); + opentimelineio::v1_0::ErrorStatus err; + auto result = tl->children_if(&err, range); + assertEqual(result.size(), 1); + assertEqual(result[0].value, cl0.value); + }); + tests.add_test( + "test_children_if_shallow_search", [] { + using namespace otio; + otio::SerializableObject::Retainer cl = + new otio::Clip(); + otio::SerializableObject::Retainer tr = + new otio::Track(); + tr->append_child(cl); + otio::SerializableObject::Retainer tl = + new otio::Timeline(); + tl->tracks()->append_child(tr); + opentimelineio::v1_0::ErrorStatus err; + auto result = tl->children_if(&err, nullopt, true); + assertEqual(result.size(), 0); + result = tl->children_if(&err, nullopt, false); + assertEqual(result.size(), 1); + assertEqual(result[0].value, cl.value); + }); + + tests.run(argc, argv); + return 0; +} diff --git a/tests/test_timeline.py b/tests/test_timeline.py index 39aaf547f..598dacdcb 100755 --- a/tests/test_timeline.py +++ b/tests/test_timeline.py @@ -557,6 +557,48 @@ def test_tracks_set_null_tracks(self): self.assertEqual(len(tl.video_tracks()), 0) self.assertTrue(isinstance(tl.tracks, otio.schema.Stack)) + def test_children_if(self): + cl = otio.schema.Clip() + tr = otio.schema.Track() + tr.append(cl) + tl = otio.schema.Timeline() + tl.tracks.append(tr) + result = tl.children_if(otio.schema.Clip) + self.assertEqual(len(result), 1) + self.assertEqual(result[0], cl) + + def test_children_if_search_range(self): + range = otio.opentime.TimeRange( + otio.opentime.RationalTime(0.0, 24.0), + otio.opentime.RationalTime(24.0, 24.0)) + cl0 = otio.schema.Clip() + cl0.source_range = range + cl1 = otio.schema.Clip() + cl1.source_range = range + cl2 = otio.schema.Clip() + cl2.source_range = range + tr = otio.schema.Track() + tr.append(cl0) + tr.append(cl1) + tr.append(cl2) + tl = otio.schema.Timeline() + tl.tracks.append(tr) + result = tl.children_if(otio.schema.Clip, range) + self.assertEqual(len(result), 1) + self.assertEqual(result[0], cl0) + + def test_children_if_shallow_search(self): + cl = otio.schema.Clip() + tr = otio.schema.Track() + tr.append(cl) + tl = otio.schema.Timeline() + tl.tracks.append(tr) + result = tl.children_if(otio.schema.Clip, shallow_search=True) + self.assertEqual(len(result), 0) + result = tl.children_if(otio.schema.Clip, shallow_search=False) + self.assertEqual(len(result), 1) + self.assertEqual(result[0], cl) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_track.cpp b/tests/test_track.cpp new file mode 100644 index 000000000..d66fcbfb5 --- /dev/null +++ b/tests/test_track.cpp @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Contributors to the OpenTimelineIO project + +#include "utils.h" + +#include +#include +#include + +#include + +namespace otime = opentime::OPENTIME_VERSION; +namespace otio = opentimelineio::OPENTIMELINEIO_VERSION; + +int +main(int argc, char** argv) +{ + Tests tests; + + tests.add_test( + "test_children_if", [] { + using namespace otio; + otio::SerializableObject::Retainer cl = + new otio::Clip(); + otio::SerializableObject::Retainer tr = + new otio::Track(); + tr->append_child(cl); + opentimelineio::v1_0::ErrorStatus err; + auto result = tr->children_if(&err); + assertEqual(result.size(), 1); + assertEqual(result[0].value, cl.value); + }); + tests.add_test( + "test_children_if_search_range", [] { + using namespace otio; + const TimeRange range(RationalTime(0.0, 24.0), RationalTime(24.0, 24.0)); + otio::SerializableObject::Retainer cl0 = + new otio::Clip(); + cl0->set_source_range(range); + otio::SerializableObject::Retainer cl1 = + new otio::Clip(); + cl1->set_source_range(range); + otio::SerializableObject::Retainer cl2 = + new otio::Clip(); + cl2->set_source_range(range); + otio::SerializableObject::Retainer tr = + new otio::Track(); + tr->append_child(cl0); + tr->append_child(cl1); + tr->append_child(cl2); + opentimelineio::v1_0::ErrorStatus err; + auto result = tr->children_if( + &err, + TimeRange(RationalTime(0.0, 24.0), RationalTime(24.0, 24.0))); + assertEqual(result.size(), 1); + assertEqual(result[0].value, cl0.value); + result = tr->children_if( + &err, + TimeRange(RationalTime(24.0, 24.0), RationalTime(24.0, 24.0))); + assertEqual(result.size(), 1); + assertEqual(result[0].value, cl1.value); + result = tr->children_if( + &err, + TimeRange(RationalTime(48.0, 24.0), RationalTime(24.0, 24.0))); + assertEqual(result.size(), 1); + assertEqual(result[0].value, cl2.value); + result = tr->children_if( + &err, + TimeRange(RationalTime(0.0, 24.0), RationalTime(48.0, 24.0))); + assertEqual(result.size(), 2); + assertEqual(result[0].value, cl0.value); + assertEqual(result[1].value, cl1.value); + result = tr->children_if( + &err, + TimeRange(RationalTime(24.0, 24.0), RationalTime(48.0, 24.0))); + assertEqual(result.size(), 2); + assertEqual(result[0].value, cl1.value); + assertEqual(result[1].value, cl2.value); + result = tr->children_if( + &err, + TimeRange(RationalTime(0.0, 24.0), RationalTime(72.0, 24.0))); + assertEqual(result.size(), 3); + assertEqual(result[0].value, cl0.value); + assertEqual(result[1].value, cl1.value); + assertEqual(result[2].value, cl2.value); + }); + tests.add_test( + "test_children_if_shallow_search", [] { + using namespace otio; + otio::SerializableObject::Retainer cl0 = + new otio::Clip(); + otio::SerializableObject::Retainer cl1 = + new otio::Clip(); + otio::SerializableObject::Retainer st = + new otio::Stack(); + st->append_child(cl1); + otio::SerializableObject::Retainer tr = + new otio::Track(); + tr->append_child(cl0); + tr->append_child(st); + opentimelineio::v1_0::ErrorStatus err; + auto result = tr->children_if(&err, nullopt, true); + assertEqual(result.size(), 1); + assertEqual(result[0].value, cl0.value); + result = tr->children_if(&err, nullopt, false); + assertEqual(result.size(), 2); + assertEqual(result[0].value, cl0.value); + assertEqual(result[1].value, cl1.value); + }); + + tests.run(argc, argv); + return 0; +} diff --git a/tests/test_track.py b/tests/test_track.py new file mode 100644 index 000000000..da4fa88f4 --- /dev/null +++ b/tests/test_track.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# SPDX-License-Identifier: Apache-2.0 +# Copyright Contributors to the OpenTimelineIO project + +import unittest + +import opentimelineio as otio +import opentimelineio.test_utils as otio_test_utils + + +class TrackTests(unittest.TestCase, otio_test_utils.OTIOAssertions): + + def test_children_if(self): + cl = otio.schema.Clip() + tr = otio.schema.Track() + tr.append(cl) + result = tr.children_if(otio.schema.Clip) + self.assertEqual(len(result), 1) + self.assertEqual(result[0], cl) + + def test_children_if_search_range(self): + range = otio.opentime.TimeRange( + otio.opentime.RationalTime(0.0, 24.0), + otio.opentime.RationalTime(24.0, 24.0)) + cl0 = otio.schema.Clip() + cl0.source_range = range + cl1 = otio.schema.Clip() + cl1.source_range = range + cl2 = otio.schema.Clip() + cl2.source_range = range + tr = otio.schema.Track() + tr.append(cl0) + tr.append(cl1) + tr.append(cl2) + result = tr.children_if(otio.schema.Clip, range) + self.assertEqual(len(result), 1) + self.assertEqual(result[0], cl0) + + def test_children_if_shallow_search(self): + cl0 = otio.schema.Clip() + cl1 = otio.schema.Clip() + st = otio.schema.Stack() + st.append(cl1) + tr = otio.schema.Track() + tr.append(cl0) + tr.append(st) + result = tr.children_if(otio.schema.Clip, shallow_search=True) + self.assertEqual(len(result), 1) + self.assertEqual(result[0], cl0) + result = tr.children_if(otio.schema.Clip, shallow_search=False) + self.assertEqual(len(result), 2) + self.assertEqual(result[0], cl0) + self.assertEqual(result[1], cl1) + + +if __name__ == '__main__': + unittest.main()