import sys, os
import unittest
from pxr import Plug, Tf, Gf
testRoot = os.path.join(os.path.dirname(__file__), 'PlugPlugins')
testPluginsDso = testRoot + '/lib'
testPluginsPython = testRoot + '/lib/python'
testPluginsDsoSearch = testPluginsDso + '/*/Resources/'
testPluginsPythonSearch = testPluginsPython + '/**/'
sys.path.append(testPluginsPython)
class NoticeListener:
def __init__(self):
self.numReceived = 0
self.newPlugins = []
self.blocked = False
self._listener = Tf.Notice.RegisterGlobally(
"PlugNotice::DidRegisterPlugins", self._OnNotice)
def Block(self):
self.blocked = True
def _OnNotice(self, notice, sender):
if not self.blocked:
self.numReceived += 1
self.newPlugins += notice.GetNewPlugins()
class TestPlug(unittest.TestCase):
@classmethod
def setUpClass(cls):
import TestPlugModuleLoaded
import TestPlugModuleLoadedBadBase
cls.listener1 = NoticeListener()
cls.listener2 = NoticeListener()
try:
Plug.Registry().RegisterPlugins(testPluginsDsoSearch)
except RuntimeError:
pass
cls.listener1.Block()
try:
Plug.Registry().RegisterPlugins(testPluginsPythonSearch)
except RuntimeError:
pass
cls.listener2.Block()
def test_Registration(self):
self.assertEqual(self.listener1.numReceived, 1)
self.assertEqual(set([p.name for p in self.listener1.newPlugins]),
set(['TestPlugDso1', 'TestPlugDso2', 'TestPlugDso3',
'TestPlugDsoUnloadable']))
self.assertEqual(self.listener2.numReceived, 2)
self.assertEqual(set([p.name for p in self.listener2.newPlugins]),
set(['TestPlugDso1', 'TestPlugDso2', 'TestPlugDso3',
'TestPlugDsoUnloadable',
'TestPlugModule1', 'TestPlugModule2', 'TestPlugModule3',
'TestPlugModuleDepBadBase', 'TestPlugModuleDepBadDep',
'TestPlugModuleDepBadDep2', 'TestPlugModuleDepBadLoad',
'TestPlugModuleDepCycle',
'TestPlugModuleLoaded', 'TestPlugModuleLoadedBadBase',
'TestPlugModuleUnloadable']))
base1Subclasses = Tf.Type.FindByName('_TestPlugBase<1>').GetAllDerivedTypes()
base1SubclassesExpected = \
('_TestPlugDerived0', 'TestPlugDerived1',
'TestPlugModule1.TestPlugPythonDerived1',
'TestPlugModuleLoaded.TestPlugPythonLoaded',
'TestPlugModuleLoadedBadBase.TestPlugPythonLoadedBadBase',
'TestPlugUnloadable', 'TestPlugPythonUnloadable')
for sc in base1SubclassesExpected:
self.assertIn(sc, base1Subclasses)
self.assertEqual(len(base1Subclasses), len(base1SubclassesExpected))
base2Subclasses = Tf.Type.FindByName('_TestPlugBase<2>').GetAllDerivedTypes()
base2SubclassesExpected = ('TestPlugDerived2',
'TestPlugModule2.TestPlugPythonDerived2')
for sc in base2SubclassesExpected:
self.assertIn(sc, base2Subclasses)
self.assertEqual(len(base2Subclasses), len(base2SubclassesExpected))
allPlugins = Plug.Registry().GetAllPlugins()
self.assertTrue(len(allPlugins) >= 8)
def test_ManufacturingCppDerivedClasses(self):
tb1 = Plug._TestPlugBase1()
self.assertEqual(tb1.GetTypeName(), '_TestPlugBase<1>')
pd1 = Plug.Registry().GetPluginForType('TestPlugDerived1')
self.assertIsNotNone(pd1)
self.assertFalse(pd1.isLoaded)
td1 = Plug._TestPlugBase1('TestPlugDerived1')
self.assertTrue(td1 and not td1.expired)
self.assertEqual(td1.GetTypeName(), 'TestPlugDerived1')
self.assertTrue(pd1.isLoaded)
tb2 = Plug._TestPlugBase2()
self.assertEqual(tb2.GetTypeName(), '_TestPlugBase<2>')
pd2 = Plug.Registry().GetPluginForType('TestPlugDerived2')
self.assertIsNotNone(pd2)
self.assertFalse(pd2.isLoaded)
td2 = Plug._TestPlugBase2('TestPlugDerived2')
self.assertTrue(td2 and not td2.expired)
self.assertEqual(td2.GetTypeName(), 'TestPlugDerived2')
self.assertTrue(pd2.isLoaded)
self.assertFalse(pd1.DeclaresType(Tf.Type('_TestPlugBase<1>'), includeSubclasses=False))
self.assertTrue(pd1.DeclaresType(Tf.Type('_TestPlugBase<1>'), includeSubclasses=True))
self.assertTrue(pd1.DeclaresType(Tf.Type('TestPlugDerived1'), includeSubclasses=False))
self.assertTrue(pd1.DeclaresType(Tf.Type('TestPlugDerived1'), includeSubclasses=True))
def test_ManufacturingPythonDerivedClasses(self):
ppd1 = Plug.Registry().GetPluginForType('TestPlugModule1.TestPlugPythonDerived1')
self.assertIsNotNone(ppd1)
self.assertFalse(ppd1.isLoaded)
self.assertTrue(ppd1.isPythonModule)
ppd2 = Plug.Registry().GetPluginForType('TestPlugModule2.TestPlugPythonDerived2')
self.assertIsNotNone(ppd2)
self.assertFalse(ppd2.isLoaded)
self.assertTrue(ppd2.isPythonModule)
ppd1.Load()
tpd1 = TestPlugModule1.TestPlugPythonDerived1()
self.assertEqual(tpd1.GetTypeName(), 'TestPlugModule1.TestPlugPythonDerived1')
self.assertTrue(ppd1.isLoaded)
ppd2.Load()
tpd2 = TestPlugModule2.TestPlugPythonDerived2()
self.assertEqual(tpd2.GetTypeName(), 'TestPlugModule2.TestPlugPythonDerived2')
self.assertTrue(ppd2.isLoaded)
ppd2.Load()
self.assertFalse(ppd1.DeclaresType(Tf.Type('_TestPlugBase<1>'),
includeSubclasses=False))
self.assertTrue(ppd1.DeclaresType(Tf.Type('_TestPlugBase<1>'),
includeSubclasses=True))
self.assertTrue(ppd1.DeclaresType(Tf.Type('TestPlugModule1.TestPlugPythonDerived1'),
includeSubclasses=False))
self.assertTrue(ppd1.DeclaresType(Tf.Type('TestPlugModule1.TestPlugPythonDerived1'),
includeSubclasses=True))
def test_LoadingPluginDependencies(self):
pd3 = Plug.Registry().GetPluginForType('TestPlugDerived3_3')
self.assertIsNotNone(pd3)
self.assertFalse(pd3.isLoaded)
ppd3 = Plug.Registry().GetPluginForType('TestPlugModule3.TestPlugPythonDerived3_3')
self.assertIsNotNone(ppd3)
self.assertFalse(ppd3.isLoaded)
Plug.Registry().GetPluginForType('TestPlugDerived3_3').Load()
self.assertTrue(pd3.isLoaded)
self.assertTrue(ppd3.isLoaded)
def test_MetadataAccess(self):
base1Subclasses = Tf.Type.FindByName('_TestPlugBase<1>').derivedTypes
self.assertIn('TestPlugUnloadable', base1Subclasses)
plugin = Plug.Registry().GetPluginForType('TestPlugUnloadable')
self.assertIsNotNone(plugin)
metadata = plugin.metadata
self.assertIsNotNone(metadata)
self.assertTrue('Types' in metadata)
self.assertTrue('TestPlugUnloadable' in metadata['Types'])
md = metadata['Types']['TestPlugUnloadable']
self.assertTrue(md ==
plugin.GetMetadataForType(Tf.Type.FindByName('TestPlugUnloadable')))
self.assertTrue('bases' in md)
self.assertTrue(md['bases'] == ['_TestPlugBase<1>'])
self.assertTrue('description' in md)
self.assertTrue(md['description'] == 'unloadable plugin')
self.assertTrue('notLoadable' in md)
self.assertTrue(md['notLoadable'] == True)
self.assertTrue('vectorInt' in md)
self.assertTrue(md['vectorInt'] == [ 1, 2, 3 ])
self.assertTrue('vectorString' in md)
self.assertTrue(md['vectorString'] == [ "f", "l", "o" ])
self.assertTrue('vectorDouble' in md)
self.assertTrue(md['vectorDouble'] == [ 1.1, 2.2, 3.3 ])
self.assertTrue('Int' in md)
self.assertTrue(md['Int'] == 4711)
self.assertTrue('Double' in md)
self.assertTrue(Gf.IsClose(md['Double'], 0.815, 1e-6))
def test_ErrorCases(self):
allplugins = Plug.Registry().GetAllPlugins()
listener = NoticeListener()
with self.assertRaises(TypeError):
badPlugin = Plug.Registry().GetPluginForType('BadSubclass')
self.assertFalse(os.path.exists('/nowhere'))
Plug.Registry().RegisterPlugins('/nowhere')
self.assertEqual(listener.numReceived, 0)
badPluginPath = testPluginsDso + '/TestPlugDsoIncomplete.framework/Resources/'
Plug.Registry().RegisterPlugins(badPluginPath)
self.assertEqual(listener.numReceived, 0)
badPluginPath = testPluginsPython + '/TestPlugModuleIncomplete'
Plug.Registry().RegisterPlugins(badPluginPath)
self.assertEqual(listener.numReceived, 0)
unknownPlug = None
with self.assertRaises(RuntimeError):
unknownPlug = Plug.Registry().GetPluginForType(Tf.Type.FindByName('Bad'))
self.assertFalse(unknownPlug)
self.assertEqual(listener.numReceived, 0)
badPlugin = Plug.Registry().GetPluginForType('TestPlugUnloadable')
self.assertIsNotNone(badPlugin)
with self.assertRaises(RuntimeError):
badPlugin.Load()
badPlugin = Plug.Registry().GetPluginForType('TestPlugPythonUnloadable')
self.assertIsNotNone(badPlugin)
with self.assertRaises(RuntimeError):
badPlugin.Load()
badPlugin = Plug.Registry().GetPluginForType('TestPlugPythonDepBadBase')
self.assertTrue(badPlugin)
with self.assertRaises(RuntimeError):
badPlugin.Load()
badPlugin = Plug.Registry().GetPluginForType('TestPlugPythonDepBadDep')
self.assertTrue(badPlugin)
with self.assertRaises(RuntimeError):
badPlugin.Load()
badPlugin = Plug.Registry().GetPluginForType('TestPlugPythonDepBadDep2')
self.assertTrue(badPlugin)
with self.assertRaises(RuntimeError):
badPlugin.Load()
badPlugin = Plug.Registry().GetPluginForType('TestPlugPythonDepBadLoad')
self.assertTrue(badPlugin)
with self.assertRaises(RuntimeError):
badPlugin.Load()
badPlugin = Plug.Registry().GetPluginForType('TestPlugPythonDepCycle')
self.assertTrue(badPlugin)
with self.assertRaises(RuntimeError):
badPlugin.Load()
Plug.Registry().RegisterPlugins(testPluginsDsoSearch)
Plug.Registry().RegisterPlugins(testPluginsPythonSearch)
self.assertEqual(allplugins, Plug.Registry().GetAllPlugins())
self.assertEqual(listener.numReceived, 0)
def test_DebugCodeExistence(self):
debugCodes = Tf.Debug.GetDebugSymbolNames()
self.assertTrue('PLUG_INFO_SEARCH' in debugCodes)
self.assertTrue('PLUG_REGISTRATION' in debugCodes)
if __name__ == '__main__':
unittest.main()