def testNotACycle( self ) : dispatcher = Gaffer.Dispatcher.create( "testDispatcher" ) fileName = "/tmp/dispatcherTest/result.txt" s = Gaffer.ScriptNode() s["n1"] = GafferTest.TextWriter() s["n1"]["mode"].setValue( "a" ) s["n1"]["fileName"].setValue( fileName ) s["n1"]["text"].setValue( "a${frame};" ) s["n2"] = GafferTest.TextWriter() s["n2"]["mode"].setValue( "a" ) s["n2"]["fileName"].setValue( fileName ) s["n2"]["text"].setValue( "b${frame};" ) s["n3"] = GafferTest.TextWriter() s["n3"]["mode"].setValue( "a" ) s["n3"]["fileName"].setValue( fileName ) s["n3"]["text"].setValue( "c${frame};" ) s["n3"]['requirements'][0].setInput( s["n2"]['requirement'] ) s["n3"]['requirements'][1].setInput( s["n1"]['requirement'] ) s["n2"]['requirements'][0].setInput( s["n1"]['requirement'] ) self.assertNotEqual( s["n1"].hash( s.context() ), s["n2"].hash( s.context() ) ) self.assertNotEqual( s["n2"].hash( s.context() ), s["n3"].hash( s.context() ) ) self.assertEqual( os.path.isfile( fileName ), False ) dispatcher.dispatch( [ s["n3"] ] ) self.assertEqual( os.path.isfile( fileName ), True ) with file( fileName, "r" ) as f : text = f.read() self.assertEqual( text, "a1;b1;c1;" )
def testInputAcceptanceInsideBoxes(self): s = Gaffer.ScriptNode() s["a"] = GafferTest.TextWriter() s["b"] = GafferTest.TextWriter() s["n"] = Gaffer.Node() s["n"]["requirement"] = Gaffer.Plug( direction=Gaffer.Plug.Direction.Out) # the ExecutableNode shouldn't accept inputs from any old node self.assertTrue(s["b"]["requirements"][0].acceptsInput( s["a"]["requirement"])) self.assertFalse(s["b"]["requirements"][0].acceptsInput( s["n"]["requirement"])) # and that shouldn't change just because we happen to be inside a box b = Gaffer.Box.create(s, Gaffer.StandardSet([s["a"], s["b"], s["n"]])) self.assertTrue(b["b"]["requirements"][0].acceptsInput( b["a"]["requirement"])) self.assertFalse(b["b"]["requirements"][0].acceptsInput( b["n"]["requirement"]))
def testBatchSize(self): dispatcher = Gaffer.Dispatcher.create("testDispatcher") dispatcher["framesMode"].setValue( Gaffer.Dispatcher.FramesMode.CustomRange) frameList = IECore.FrameList.parse("2-6x2") dispatcher["frameRange"].setValue(str(frameList)) fileName = "/tmp/dispatcherTest/result.txt" s = Gaffer.ScriptNode() s["n1"] = GafferTest.TextWriter() s["n1"]["mode"].setValue("a") s["n1"]["fileName"].setValue(fileName) s["n1"]["text"].setValue("n1 on ${frame};") s["n2"] = GafferTest.TextWriter() s["n2"]["mode"].setValue("a") s["n2"]["fileName"].setValue(fileName) s["n2"]["text"].setValue("n2 on ${frame};") s["n3"] = GafferTest.TextWriter(requiresSequenceExecution=True) s["n3"]["mode"].setValue("a") s["n3"]["fileName"].setValue(fileName) s["n3"]["text"].setValue("n3 on ${frame};") s["n4"] = GafferTest.TextWriter() s["n4"]["mode"].setValue("a") s["n4"]["fileName"].setValue(fileName) s["n4"]["text"].setValue("n4 on ${frame};") s["n3"]['requirements'][0].setInput(s["n1"]['requirement']) s["n3"]['requirements'][1].setInput(s["n2"]['requirement']) s["n4"]['requirements'][0].setInput(s["n3"]['requirement']) self.assertEqual(os.path.isfile(fileName), False) dispatcher.dispatch([s["n4"]]) shutil.rmtree(dispatcher.jobDirectory()) self.assertEqual(os.path.isfile(fileName), True) with file(fileName, "r") as f: text = f.read() # all frames of n1 and n2 interleaved, followed by the n3 sequence, followed by n4 on all frames expectedText = "n1 on 2;n2 on 2;n1 on 4;n2 on 4;n1 on 6;n2 on 6;n3 on 2;n3 on 4;n3 on 6;n4 on 2;n4 on 4;n4 on 6;" self.assertEqual(text, expectedText) # dispatch again with differnt batch sizes s["n1"]["dispatcher"]["batchSize"].setValue(2) s["n2"]["dispatcher"]["batchSize"].setValue(5) os.remove(fileName) self.assertEqual(os.path.isfile(fileName), False) dispatcher.dispatch([s["n4"]]) shutil.rmtree(dispatcher.jobDirectory()) self.assertEqual(os.path.isfile(fileName), True) with file(fileName, "r") as f: text = f.read() # first 2 frames of n1, followed by all frames of n2, followed by last frame of n1, followed by the n3 sequence, followed by n4 on all frames expectedText = "n1 on 2;n1 on 4;n2 on 2;n2 on 4;n2 on 6;n1 on 6;n3 on 2;n3 on 4;n3 on 6;n4 on 2;n4 on 4;n4 on 6;" self.assertEqual(text, expectedText)
def testInputAcceptanceFromDots(self): e1 = GafferTest.TextWriter() e2 = GafferTest.TextWriter() d1 = Gaffer.Dot() d1.setup(e1["requirement"]) self.assertTrue(e2["requirements"][0].acceptsInput(d1["out"])) d1["in"].setInput(e1["requirement"]) self.assertTrue(e2["requirements"][0].acceptsInput(d1["out"]))
def testRequiresSequenceExecution(self): dispatcher = Gaffer.Dispatcher.create("testDispatcher") dispatcher["framesMode"].setValue( Gaffer.Dispatcher.FramesMode.CustomRange) frameList = IECore.FrameList.parse("2-6x2") dispatcher["frameRange"].setValue(str(frameList)) fileName = "/tmp/dispatcherTest/result.txt" s = Gaffer.ScriptNode() s["n1"] = GafferTest.TextWriter() s["n1"]["mode"].setValue("a") s["n1"]["fileName"].setValue(fileName) s["n1"]["text"].setValue("n1 on ${frame};") s["n2"] = GafferTest.TextWriter(requiresSequenceExecution=True) s["n2"]["mode"].setValue("a") s["n2"]["fileName"].setValue(fileName) s["n2"]["text"].setValue("n2 on ${frame};") s["n3"] = GafferTest.TextWriter() s["n3"]["mode"].setValue("a") s["n3"]["fileName"].setValue(fileName) s["n3"]["text"].setValue("n3 on ${frame};") s["n2"]['requirements'][0].setInput(s["n1"]['requirement']) s["n3"]['requirements'][0].setInput(s["n2"]['requirement']) self.assertEqual(os.path.isfile(fileName), False) dispatcher.dispatch([s["n3"]]) shutil.rmtree(dispatcher.jobDirectory()) self.assertEqual(os.path.isfile(fileName), True) with file(fileName, "r") as f: text = f.read() # n1 on all frames, followed by the n2 sequence, followed by n3 on all frames expectedText = "n1 on 2;n1 on 4;n1 on 6;n2 on 2;n2 on 4;n2 on 6;n3 on 2;n3 on 4;n3 on 6;" self.assertEqual(text, expectedText) # make sure n2 gets frames in sorted order dispatcher["frameRange"].setValue("2,6,4") os.remove(fileName) self.assertEqual(os.path.isfile(fileName), False) dispatcher.dispatch([s["n3"]]) shutil.rmtree(dispatcher.jobDirectory()) self.assertEqual(os.path.isfile(fileName), True) with file(fileName, "r") as f: text = f.read() # n1 in requested order, followed by the n2 sequence in sorted order, followed by n3 in the requested order expectedText = "n1 on 2;n1 on 6;n1 on 4;n2 on 2;n2 on 4;n2 on 6;n3 on 2;n3 on 6;n3 on 4;" self.assertEqual(text, expectedText)
def testColorRange(self): script = Gaffer.ScriptNode() script["writer"] = GafferTest.TextWriter() script["writer"]["fileName"].setValue(self.temporaryDirectory() + "/${wedge:index}.txt") script["expression"] = Gaffer.Expression() script["expression"].setExpression( 'c = context["wedge:value"]; parent["writer"]["text"] = "%.1f %.1f %.1f" % ( c[0], c[1], c[2] )' ) script["wedge"] = Gaffer.Wedge() script["wedge"]["requirements"][0].setInput( script["writer"]["requirement"]) script["wedge"]["mode"].setValue(int(Gaffer.Wedge.Mode.ColorRange)) script["wedge"]["colorSteps"].setValue(3) self.__dispatcher().dispatch([script["wedge"]]) self.assertEqual( set(glob.glob(self.temporaryDirectory() + "/*.txt")), { self.temporaryDirectory() + "/0.txt", self.temporaryDirectory() + "/1.txt", self.temporaryDirectory() + "/2.txt", }) self.assertEqual(next(open(self.temporaryDirectory() + "/0.txt")), "0.0 0.0 0.0") self.assertEqual(next(open(self.temporaryDirectory() + "/1.txt")), "0.5 0.5 0.5") self.assertEqual(next(open(self.temporaryDirectory() + "/2.txt")), "1.0 1.0 1.0")
def testIntRange(self): script = Gaffer.ScriptNode() script["writer"] = GafferTest.TextWriter() script["writer"]["fileName"].setValue(self.temporaryDirectory() + "/${number}.txt") script["wedge"] = Gaffer.Wedge() script["wedge"]["requirements"][0].setInput( script["writer"]["requirement"]) script["wedge"]["variable"].setValue("number") script["wedge"]["mode"].setValue(int(Gaffer.Wedge.Mode.IntRange)) script["wedge"]["intMin"].setValue(3) script["wedge"]["intMax"].setValue(7) script["wedge"]["intStep"].setValue(2) self.__dispatcher().dispatch([script["wedge"]]) self.assertEqual( set(glob.glob(self.temporaryDirectory() + "/*.txt")), { self.temporaryDirectory() + "/3.txt", self.temporaryDirectory() + "/5.txt", self.temporaryDirectory() + "/7.txt", })
def testFloatList(self): script = Gaffer.ScriptNode() script["writer"] = GafferTest.TextWriter() script["writer"]["fileName"].setValue(self.temporaryDirectory() + "/${wedge:index}.txt") script["writer"]["text"].setValue("${wedge:value}") script["wedge"] = Gaffer.Wedge() script["wedge"]["requirements"][0].setInput( script["writer"]["requirement"]) script["wedge"]["mode"].setValue(int(Gaffer.Wedge.Mode.FloatList)) script["wedge"]["floats"].setValue( IECore.FloatVectorData([1.25, 2.75, 44.0])) self.__dispatcher().dispatch([script["wedge"]]) self.assertEqual( set(glob.glob(self.temporaryDirectory() + "/*.txt")), { self.temporaryDirectory() + "/0.txt", self.temporaryDirectory() + "/1.txt", self.temporaryDirectory() + "/2.txt", }) self.assertEqual(next(open(self.temporaryDirectory() + "/0.txt")), "1.25") self.assertEqual(next(open(self.temporaryDirectory() + "/1.txt")), "2.75") self.assertEqual(next(open(self.temporaryDirectory() + "/2.txt")), "44")
def testIgnoreScriptLoadErrors(self): s = Gaffer.ScriptNode() s["n"] = GafferTest.TextWriter() s["n"]["fileName"].setValue( "/tmp/dispatcherTest/scriptLoadErrorTest.txt") s["n"]["text"].setValue("test") # because this doesn't have the dynamic flag set, # it won't serialise/load properly. s["n"]["user"]["badPlug"] = Gaffer.IntPlug() s["n"]["user"]["badPlug"].setValue(10) dispatcher = Gaffer.Dispatcher.create("LocalTest") dispatcher["executeInBackground"].setValue(True) dispatcher.dispatch([s["n"]]) dispatcher.jobPool().waitForAll() self.assertFalse( os.path.isfile("/tmp/dispatcherTest/scriptLoadErrorTest.txt")) dispatcher["ignoreScriptLoadErrors"].setValue(True) dispatcher.dispatch([s["n"]]) dispatcher.jobPool().waitForAll() self.assertTrue( os.path.isfile("/tmp/dispatcherTest/scriptLoadErrorTest.txt"))
def testContextLockedDuringBackgroundDispatch(self): s = Gaffer.ScriptNode() s["n1"] = GafferTest.TextWriter() s["n1"]["fileName"].setValue("/tmp/dispatcherTest/out.txt") s["n1"]["text"].setValue("n1 on ${frame} with ${foo}") dispatcher = Gaffer.Dispatcher.create("LocalTest") dispatcher["executeInBackground"].setValue(True) c = Gaffer.Context(s.context()) c["foo"] = "foo" with c: dispatcher.dispatch([s["n1"]]) self.assertFalse(os.path.isfile("/tmp/dispatcherTest/out.txt")) foo = s["variables"].addMember("foo", IECore.StringData("foo")) dispatcher.jobPool().waitForAll() self.assertTrue(os.path.isfile("/tmp/dispatcherTest/out.txt")) text = "".join(open("/tmp/dispatcherTest/out.txt").readlines()) self.assertEqual(text, "n1 on 1 with foo")
def testKill(self): s = Gaffer.ScriptNode() s["n1"] = GafferTest.TextWriter() s["n1"]["fileName"].setValue("/tmp/dispatcherTest/n1_####.txt") s["n1"]["text"].setValue("n1 on ${frame}") dispatcher = Gaffer.Dispatcher.create("LocalTest") dispatcher["executeInBackground"].setValue(True) self.assertEqual(len(dispatcher.jobPool().jobs()), 0) dispatcher.dispatch([s["n1"]]) self.assertEqual(len(dispatcher.jobPool().jobs()), 1) # the execution hasn't finished yet self.assertFalse( os.path.isfile(s.context().substitute( s["n1"]["fileName"].getValue()))) # kill the job dispatcher.jobPool().jobs()[0].kill() # wait long enough for the process to die dispatcher.jobPool().waitForAll() self.assertEqual(len(dispatcher.jobPool().jobs()), 0) # make sure it never wrote the file self.assertFalse( os.path.isfile(s.context().substitute( s["n1"]["fileName"].getValue())))
def testMultipleDispatchers(self): s = Gaffer.ScriptNode() s["n1"] = GafferTest.TextWriter() s["n1"]["fileName"].setValue("/tmp/dispatcherTest/n1_####.txt") s["n1"]["text"].setValue("n1 on ${frame}") dispatcher = Gaffer.Dispatcher.create("LocalTest") dispatcher["executeInBackground"].setValue(True) dispatcher2 = Gaffer.Dispatcher.create("LocalTest") dispatcher2["executeInBackground"].setValue(True) dispatcher.dispatch([s["n1"]]) c = s.context() c.setFrame(2) with c: dispatcher2.dispatch([s["n1"]]) # wait long enough for background execution to finish self.assertEqual(len(dispatcher.jobPool().jobs()), 2) dispatcher.jobPool().waitForAll() self.assertEqual(len(dispatcher.jobPool().jobs()), 0) self.assertTrue( os.path.isfile(s.context().substitute( s["n1"]["fileName"].getValue()))) self.assertTrue( os.path.isfile(c.substitute(s["n1"]["fileName"].getValue())))
def testFloatRange(self): script = Gaffer.ScriptNode() script["writer"] = GafferTest.TextWriter() script["writer"]["fileName"].setValue( "/tmp/gafferWedgeTest/${wedge:index}.txt") script["writer"]["text"].setValue("${wedge:value}") script["wedge"] = Gaffer.Wedge() script["wedge"]["requirements"][0].setInput( script["writer"]["requirement"]) script["wedge"]["mode"].setValue(int(Gaffer.Wedge.Mode.FloatRange)) script["wedge"]["floatMin"].setValue(0) script["wedge"]["floatMax"].setValue(1) script["wedge"]["floatSteps"].setValue(5) self.__dispatcher().dispatch([script["wedge"]]) self.assertEqual( set(glob.glob("/tmp/gafferWedgeTest/*.txt")), { "/tmp/gafferWedgeTest/0.txt", "/tmp/gafferWedgeTest/1.txt", "/tmp/gafferWedgeTest/2.txt", "/tmp/gafferWedgeTest/3.txt", "/tmp/gafferWedgeTest/4.txt", }) self.assertEqual(next(open("/tmp/gafferWedgeTest/0.txt")), "0") self.assertEqual(next(open("/tmp/gafferWedgeTest/1.txt")), "0.25") self.assertEqual(next(open("/tmp/gafferWedgeTest/2.txt")), "0.5") self.assertEqual(next(open("/tmp/gafferWedgeTest/3.txt")), "0.75") self.assertEqual(next(open("/tmp/gafferWedgeTest/4.txt")), "1")
def testContext(self): script = Gaffer.ScriptNode() script["writer"] = GafferTest.TextWriter() script["writer"]["fileName"].setValue(self.temporaryDirectory() + "/${name}.####.txt") script["wedge"] = Gaffer.Wedge() script["wedge"]["requirements"][0].setInput( script["writer"]["requirement"]) script["wedge"]["variable"].setValue("name") script["wedge"]["mode"].setValue(int(Gaffer.Wedge.Mode.StringList)) script["wedge"]["strings"].setValue( IECore.StringVectorData(["tom", "dick", "harry"])) self.__dispatcher(frameRange="21-22").dispatch([script["wedge"]]) self.assertEqual( set(glob.glob(self.temporaryDirectory() + "/*.txt")), { self.temporaryDirectory() + "/tom.0021.txt", self.temporaryDirectory() + "/tom.0022.txt", self.temporaryDirectory() + "/dick.0021.txt", self.temporaryDirectory() + "/dick.0022.txt", self.temporaryDirectory() + "/harry.0021.txt", self.temporaryDirectory() + "/harry.0022.txt", })
def testUpstreamConstant(self): script = Gaffer.ScriptNode() script["constant"] = GafferTest.CountingExecutableNode() script["writer"] = GafferTest.TextWriter() script["writer"]["requirements"][0].setInput( script["constant"]["requirement"]) script["writer"]["fileName"].setValue(self.temporaryDirectory() + "/${name}.txt") script["wedge"] = Gaffer.Wedge() script["wedge"]["requirements"][0].setInput( script["writer"]["requirement"]) script["wedge"]["variable"].setValue("name") script["wedge"]["mode"].setValue(int(Gaffer.Wedge.Mode.StringList)) script["wedge"]["strings"].setValue( IECore.StringVectorData(["tom", "dick", "harry"])) self.__dispatcher().dispatch([script["wedge"]]) self.assertEqual( set(glob.glob(self.temporaryDirectory() + "/*.txt")), { self.temporaryDirectory() + "/tom.txt", self.temporaryDirectory() + "/dick.txt", self.temporaryDirectory() + "/harry.txt", }) # Even though the constant node is upstream from the wedge, # it should only execute once because it doesn't reference # the wedge variable at all. self.assertEqual(script["constant"].executionCount, 1)
def testDispatcherSignals(self): class CapturingSlot2(list): def __init__(self, *signals): self.__connections = [] for s in signals: self.__connections.append( s.connect(Gaffer.WeakMethod(self.__slot))) def __slot(self, d, nodes): self.append((d, nodes)) preCs = CapturingSlot2(Gaffer.Dispatcher.preDispatchSignal()) self.assertEqual(len(preCs), 0) postCs = GafferTest.CapturingSlot( Gaffer.Dispatcher.postDispatchSignal()) self.assertEqual(len(postCs), 0) s = Gaffer.ScriptNode() s["n1"] = GafferTest.TextWriter() s["n1"]["fileName"].setValue("/tmp/dispatcherTest/n1_####.txt") s["n1"]["text"].setValue("n1 on ${frame}") dispatcher = Gaffer.Dispatcher.dispatcher("Local") dispatcher.dispatch([s["n1"]]) self.assertEqual(len(preCs), 1) self.failUnless(preCs[0][0].isSame(dispatcher)) self.assertEqual(preCs[0][1], [s["n1"]]) self.assertEqual(len(postCs), 1) self.failUnless(postCs[0][0].isSame(dispatcher)) self.assertEqual(postCs[0][1], [s["n1"]])
def testBackgroundBatchesCanAccessJobDirectory(self): s = Gaffer.ScriptNode() s["w"] = GafferTest.TextWriter() s["w"]["fileName"].setValue("${dispatcher:jobDirectory}/test.####.txt") s["w"]["text"].setValue( "w on ${frame} from ${dispatcher:jobDirectory}") dispatcher = Gaffer.Dispatcher.create("LocalTest") dispatcher["executeInBackground"].setValue(True) dispatcher["framesMode"].setValue( Gaffer.Dispatcher.FramesMode.CustomRange) frameList = IECore.FrameList.parse("2-6x2") dispatcher["frameRange"].setValue(str(frameList)) dispatcher.dispatch([s["w"]]) dispatcher.jobPool().waitForAll() # a single dispatch should have the same job directory for all batches jobDir = dispatcher.jobDirectory() self.assertEqual(next(open("%s/test.0002.txt" % jobDir)), "w on 2 from %s" % jobDir) self.assertEqual(next(open("%s/test.0004.txt" % jobDir)), "w on 4 from %s" % jobDir) self.assertEqual(next(open("%s/test.0006.txt" % jobDir)), "w on 6 from %s" % jobDir)
def testExecuteInBackground(self): preCs = GafferTest.CapturingSlot( Gaffer.LocalDispatcher.preDispatchSignal()) self.assertEqual(len(preCs), 0) postCs = GafferTest.CapturingSlot( Gaffer.LocalDispatcher.postDispatchSignal()) self.assertEqual(len(postCs), 0) s = Gaffer.ScriptNode() s["n1"] = GafferTest.TextWriter() s["n1"]["fileName"].setValue("/tmp/dispatcherTest/n1_####.txt") s["n1"]["text"].setValue("n1 on ${frame}") dispatcher = Gaffer.Dispatcher.dispatcher("Local") dispatcher["executeInBackground"].setValue(True) dispatcher.dispatch([s["n1"]]) # the dispatching started and finished self.assertEqual(len(preCs), 1) self.assertEqual(len(postCs), 1) # but the execution hasn't finished yet self.assertFalse( os.path.isfile(s.context().substitute( s["n1"]["fileName"].getValue()))) # wait long enough to finish execution import time time.sleep(2) self.assertTrue( os.path.isfile(s.context().substitute( s["n1"]["fileName"].getValue())))
def testContextVariation(self): s = Gaffer.ScriptNode() context = Gaffer.Context(s.context()) context["script:name"] = "notTheRealScriptName" context["textWriter:replace"] = IECore.StringVectorData([" ", "\n"]) s["n1"] = GafferTest.TextWriter() s["n1"]["fileName"].setValue( "/tmp/dispatcherTest/${script:name}_####.txt") s["n1"]["text"].setValue("${script:name} on ${frame}") fileName = context.substitute(s["n1"]["fileName"].getValue()) self.assertFalse(os.path.isfile(fileName)) with context: Gaffer.Dispatcher.dispatcher("Local").dispatch([s["n1"]]) self.assertTrue(os.path.isfile(fileName)) self.assertTrue( os.path.basename(fileName).startswith(context["script:name"])) with file(fileName, "r") as f: text = f.read() expected = "%s on %d" % (context["script:name"], context.getFrame()) expected = expected.replace(context["textWriter:replace"][0], context["textWriter:replace"][1]) self.assertEqual(text, expected)
def testReferencePromotedRequirementPlug(self): s = Gaffer.ScriptNode() s["b"] = Gaffer.Box() s["b"]["e"] = GafferTest.TextWriter() p = s["b"].promotePlug(s["b"]["e"]["requirements"][0]) p.setName("p") s["b"].exportForReference(self.temporaryDirectory() + "/test.grf") s["r"] = Gaffer.Reference() s["r"].load(self.temporaryDirectory() + "/test.grf") s["e"] = GafferTest.TextWriter() s["r"]["p"].setInput(s["e"]["requirement"])
def testInputAcceptanceFromBoxes(self): s = Gaffer.ScriptNode() s["n"] = Gaffer.Node() s["n"]["requirement"] = Gaffer.Plug( direction=Gaffer.Plug.Direction.Out) s["a"] = GafferTest.TextWriter() s["b"] = Gaffer.Box() s["b"]["a"] = GafferTest.TextWriter() s["b"]["b"] = GafferTest.TextWriter() s["b"]["n"] = Gaffer.Node() s["b"]["n"]["requirement"] = Gaffer.Plug( direction=Gaffer.Plug.Direction.Out) s["b"]["in"] = s["b"]["a"]["requirements"][0].createCounterpart( "in", Gaffer.Plug.Direction.In) s["b"]["out"] = s["b"]["a"]["requirement"].createCounterpart( "out", Gaffer.Plug.Direction.Out) # ExecutableNodes should accept connections speculatively from unconnected box inputs and outputs self.assertTrue(s["b"]["a"]["requirements"][0].acceptsInput( s["b"]["in"])) self.assertTrue(s["a"]["requirements"][0].acceptsInput(s["b"]["out"])) # but should reject connections to connected box inputs and outputs if they're unsuitable. s["b"]["in"].setInput(s["n"]["requirement"]) self.assertFalse(s["b"]["a"]["requirements"][0].acceptsInput( s["b"]["in"])) s["b"]["out"].setInput(s["b"]["n"]["requirement"]) self.assertFalse(s["a"]["requirements"][0].acceptsInput(s["b"]["out"])) # and accept them again if they provide indirect access to an ExecutableNode s["c"] = GafferTest.TextWriter() s["b"]["in"].setInput(s["c"]["requirement"]) self.assertTrue(s["b"]["a"]["requirements"][0].acceptsInput( s["b"]["in"])) s["b"]["out"].setInput(s["b"]["b"]["requirement"]) self.assertTrue(s["a"]["requirements"][0].acceptsInput(s["b"]["out"]))
def testFloatByPointOne(self): script = Gaffer.ScriptNode() script["writer"] = GafferTest.TextWriter() script["writer"]["fileName"].setValue(self.temporaryDirectory() + "/${wedge:index}.txt") script["writer"]["text"].setValue("${wedge:value}") script["wedge"] = Gaffer.Wedge() script["wedge"]["requirements"][0].setInput( script["writer"]["requirement"]) script["wedge"]["mode"].setValue(int(Gaffer.Wedge.Mode.FloatRange)) script["wedge"]["floatMin"].setValue(0) script["wedge"]["floatMax"].setValue(1) script["wedge"]["floatSteps"].setValue(11) self.__dispatcher().dispatch([script["wedge"]]) self.assertEqual( set(glob.glob(self.temporaryDirectory() + "/*.txt")), { self.temporaryDirectory() + "/0.txt", self.temporaryDirectory() + "/1.txt", self.temporaryDirectory() + "/2.txt", self.temporaryDirectory() + "/3.txt", self.temporaryDirectory() + "/4.txt", self.temporaryDirectory() + "/5.txt", self.temporaryDirectory() + "/6.txt", self.temporaryDirectory() + "/7.txt", self.temporaryDirectory() + "/8.txt", self.temporaryDirectory() + "/9.txt", self.temporaryDirectory() + "/10.txt", }) self.assertAlmostEqual( float(next(open(self.temporaryDirectory() + "//0.txt"))), 0) self.assertAlmostEqual( float(next(open(self.temporaryDirectory() + "//1.txt"))), 0.1) self.assertAlmostEqual( float(next(open(self.temporaryDirectory() + "//2.txt"))), 0.2) self.assertAlmostEqual( float(next(open(self.temporaryDirectory() + "//3.txt"))), 0.3) self.assertAlmostEqual( float(next(open(self.temporaryDirectory() + "//4.txt"))), 0.4) self.assertAlmostEqual( float(next(open(self.temporaryDirectory() + "//5.txt"))), 0.5) self.assertAlmostEqual( float(next(open(self.temporaryDirectory() + "//6.txt"))), 0.6) self.assertAlmostEqual( float(next(open(self.temporaryDirectory() + "//7.txt"))), 0.7) self.assertAlmostEqual( float(next(open(self.temporaryDirectory() + "//8.txt"))), 0.8) self.assertAlmostEqual( float(next(open(self.temporaryDirectory() + "//9.txt"))), 0.9) self.assertAlmostEqual( float(next(open(self.temporaryDirectory() + "//10.txt"))), 1)
def testInputAcceptanceFromBoxes(self): s = Gaffer.ScriptNode() s["n"] = Gaffer.Node() s["n"]["requirement"] = Gaffer.Plug( direction=Gaffer.Plug.Direction.Out) s["a"] = GafferTest.TextWriter() s["b"] = Gaffer.Box() s["b"]["a"] = GafferTest.TextWriter() s["b"]["b"] = GafferTest.TextWriter() s["b"]["n"] = Gaffer.Node() s["b"]["n"]["requirement"] = Gaffer.Plug( direction=Gaffer.Plug.Direction.Out) s["b"]["in"] = s["b"]["a"]["requirements"][0].createCounterpart( "in", Gaffer.Plug.Direction.In) s["b"]["out"] = s["b"]["a"]["requirement"].createCounterpart( "out", Gaffer.Plug.Direction.Out) # ExecutableNodes should accept connections speculatively from unconnected box inputs and outputs self.assertTrue(s["b"]["a"]["requirements"][0].acceptsInput( s["b"]["in"])) self.assertTrue(s["a"]["requirements"][0].acceptsInput(s["b"]["out"])) # But the promoted plugs shouldn't accept any old inputs. self.assertFalse(s["b"]["in"].acceptsInput(s["n"]["requirement"])) self.assertFalse(s["b"]["out"].acceptsInput( s["b"]["n"]["requirement"])) # We should be able to connect them up only to other appropriate requirement plugs. self.assertTrue(s["a"]["requirements"][0].acceptsInput(s["b"]["out"])) s["c"] = GafferTest.TextWriter() s["b"]["in"].setInput(s["c"]["requirement"]) self.assertTrue(s["b"]["a"]["requirements"][0].acceptsInput( s["b"]["in"])) s["b"]["out"].setInput(s["b"]["b"]["requirement"]) self.assertTrue(s["a"]["requirements"][0].acceptsInput(s["b"]["out"]))
def testReferencePromotedRequirementsPlug( self ) : s = Gaffer.ScriptNode() s["b"] = Gaffer.Box() s["b"]["e"] = GafferTest.TextWriter() p = s["b"].promotePlug( s["b"]["e"]["requirements"] ) p.setName( "p" ) s["b"].exportForReference( "/tmp/test.grf" ) s["r"] = Gaffer.Reference() s["r"].load( "/tmp/test.grf" ) s["e"] = GafferTest.TextWriter() s["r"]["p"][0].setInput( s["e"]["requirement"] ) self.assertTrue( s["r"]["e"]["requirements"][0].source().isSame( s["e"]["requirement"] ) )
def testCyclesThrow(self): dispatcher = Gaffer.Dispatcher.create("testDispatcher") fileName = "/tmp/dispatcherTest/result.txt" s = Gaffer.ScriptNode() s["n1"] = GafferTest.TextWriter() s["n1"]["mode"].setValue("a") s["n1"]["fileName"].setValue(fileName) s["n1"]["text"].setValue("a${frame};") s["n2"] = GafferTest.TextWriter() s["n2"]["mode"].setValue("a") s["n2"]["fileName"].setValue(fileName) s["n2"]["text"].setValue("b${frame};") s["n3"] = GafferTest.TextWriter() s["n3"]["mode"].setValue("a") s["n3"]["fileName"].setValue(fileName) s["n3"]["text"].setValue("c${frame};") s["n4"] = GafferTest.TextWriter() s["n4"]["mode"].setValue("a") s["n4"]["fileName"].setValue(fileName) s["n4"]["text"].setValue("d${frame};") s["n4"]['requirements'][0].setInput(s["n3"]['requirement']) s["n3"]['requirements'][0].setInput(s["n2"]['requirement']) s["n2"]['requirements'][0].setInput(s["n1"]['requirement']) s["n1"]['requirements'][0].setInput(s["n4"]['requirement']) self.assertNotEqual(s["n1"].hash(s.context()), s["n2"].hash(s.context())) self.assertNotEqual(s["n2"].hash(s.context()), s["n3"].hash(s.context())) self.assertNotEqual(s["n3"].hash(s.context()), s["n4"].hash(s.context())) self.assertNotEqual(s["n1"].hash(s.context()), s["n4"].hash(s.context())) self.assertEqual(os.path.isfile(fileName), False) self.assertRaises(RuntimeError, dispatcher.dispatch, [s["n4"]]) self.assertEqual(os.path.isfile(fileName), False)
def testDispatchBadCustomRange( self ) : dispatcher = Gaffer.Dispatcher.dispatcher( "Local" ) dispatcher["framesMode"].setValue( Gaffer.Dispatcher.FramesMode.CustomRange ) dispatcher["frameRange"].setValue( "notAFrameRange" ) s = Gaffer.ScriptNode() s["n1"] = GafferTest.TextWriter() s["n1"]["fileName"].setValue( "/tmp/dispatcherTest/n1_####.txt" ) s["n1"]["text"].setValue( "n1 on ${frame}" ) self.assertRaises( RuntimeError, dispatcher.dispatch, [ s["n1"] ] ) self.assertFalse( os.path.isfile( s.context().substitute( s["n1"]["fileName"].getValue() ) ) )
def testDoesNotRequireSequenceExecution(self): dispatcher = Gaffer.Dispatcher.create("testDispatcher") dispatcher["framesMode"].setValue( Gaffer.Dispatcher.FramesMode.CustomRange) frameList = IECore.FrameList.parse("2-6x2") dispatcher["frameRange"].setValue(str(frameList)) fileName = "/tmp/dispatcherTest/result.txt" s = Gaffer.ScriptNode() s["n1"] = GafferTest.TextWriter() s["n1"]["mode"].setValue("a") s["n1"]["fileName"].setValue(fileName) s["n1"]["text"].setValue("n1 on ${frame};") s["n2"] = GafferTest.TextWriter() s["n2"]["mode"].setValue("a") s["n2"]["fileName"].setValue(fileName) s["n2"]["text"].setValue("n2 on ${frame};") s["n3"] = GafferTest.TextWriter() s["n3"]["mode"].setValue("a") s["n3"]["fileName"].setValue(fileName) s["n3"]["text"].setValue("n3 on ${frame};") s["n2"]['requirements'][0].setInput(s["n1"]['requirement']) s["n3"]['requirements'][0].setInput(s["n2"]['requirement']) self.assertEqual(os.path.isfile(fileName), False) dispatcher.dispatch([s["n3"]]) shutil.rmtree(dispatcher.jobDirectory()) self.assertEqual(os.path.isfile(fileName), True) with file(fileName, "r") as f: text = f.read() # all nodes on frame 1, followed by all nodes on frame 2, followed by all nodes on frame 3 expectedText = "n1 on 2;n2 on 2;n3 on 2;n1 on 4;n2 on 4;n3 on 4;n1 on 6;n2 on 6;n3 on 6;" self.assertEqual(text, expectedText)
def testContextChange( self ) : class ContextChangingExecutable( Gaffer.ExecutableNode ) : def __init__( self, name = "ContextChangingExecutable" ) : Gaffer.ExecutableNode.__init__( self, name ) def requirements( self, context ) : assert( context.isSame( Gaffer.Context.current() ) ) upstreamContext = Gaffer.Context( context ) upstreamContext["myText"] = "testing 123" upstreamContext.setFrame( 10 ) result = [] for plug in self["requirements"] : node = plug.source().node() if node.isSame( self ) or not isinstance( node, Gaffer.ExecutableNode ): continue result.append( self.Task( node, upstreamContext ) ) return result def hash( self, context ) : return IECore.MurmurHash() def execute( self ) : pass s = Gaffer.ScriptNode() s["w"] = GafferTest.TextWriter() s["w"]["fileName"].setValue( "/tmp/dispatcherTest/test.####.txt" ) s["e"] = Gaffer.Expression() s["e"]["engine"].setValue( "python" ) s["e"]["expression"].setValue( 'parent["w"]["text"] = context["myText"]' ) s["c"] = ContextChangingExecutable() s["c"]["requirements"][0].setInput( s["w"]["requirement"] ) Gaffer.Dispatcher.create( "testDispatcher" ).dispatch( [ s["c"] ] ) self.assertEqual( next( open( "/tmp/dispatcherTest/test.0010.txt" ) ), "testing 123" )
def testDispatchDifferentFrame( self ) : s = Gaffer.ScriptNode() s["n1"] = GafferTest.TextWriter() s["n1"]["fileName"].setValue( "/tmp/dispatcherTest/n1_####.txt" ) s["n1"]["text"].setValue( "n1 on ${frame}" ) context = Gaffer.Context( s.context() ) context.setFrame( s.context().getFrame() + 10 ) with context : Gaffer.Dispatcher.dispatcher( "Local" ).dispatch( [ s["n1"] ] ) fileName = context.substitute( s["n1"]["fileName"].getValue() ) self.assertTrue( os.path.isfile( fileName ) ) with file( fileName, "r" ) as f : text = f.read() self.assertEqual( text, "%s on %d" % ( s["n1"].getName(), context.getFrame() ) )
def testSpecialCharactersInScriptFileName(self): s = Gaffer.ScriptNode() s["fileName"].setValue(self.__scriptFileNameWithSpecialCharacters) s["t"] = GafferTest.TextWriter() s["t"]["fileName"].setValue(self.__outputTextFile) s.save() p = subprocess.Popen( "gaffer execute -script '%s'" % self.__scriptFileNameWithSpecialCharacters, shell=True, stderr=subprocess.PIPE, ) p.wait() self.assertEqual(p.returncode, 0) self.assertTrue(os.path.exists(self.__outputTextFile))