зеркало из https://github.com/mozilla/pjs.git
bug 654448 - remove xpt.py's Typelib.merge, move all the logic into xpt_link (also make it a lot faster). r=khuey
This commit is contained in:
Родитель
df74054797
Коммит
ad83523c70
|
@ -378,7 +378,7 @@ class TestInterfaceCmp(unittest.TestCase):
|
|||
methods=[m])
|
||||
self.assert_(i2 == i1)
|
||||
|
||||
class TestTypelibMerge(unittest.TestCase):
|
||||
class TestXPTLink(unittest.TestCase):
|
||||
def test_mergeDifferent(self):
|
||||
"""
|
||||
Test that merging two typelibs with completely different interfaces
|
||||
|
@ -391,12 +391,12 @@ class TestTypelibMerge(unittest.TestCase):
|
|||
t2 = xpt.Typelib()
|
||||
# add an unresolved interface
|
||||
t2.interfaces.append(xpt.Interface("IBar"))
|
||||
t1.merge(t2)
|
||||
t3 = xpt.xpt_link([t1, t2])
|
||||
|
||||
self.assertEqual(2, len(t1.interfaces))
|
||||
self.assertEqual(2, len(t3.interfaces))
|
||||
# Interfaces should wind up sorted
|
||||
self.assertEqual("IBar", t1.interfaces[0].name)
|
||||
self.assertEqual("IFoo", t1.interfaces[1].name)
|
||||
self.assertEqual("IBar", t3.interfaces[0].name)
|
||||
self.assertEqual("IFoo", t3.interfaces[1].name)
|
||||
|
||||
# Add some IID values
|
||||
t1 = xpt.Typelib()
|
||||
|
@ -405,12 +405,12 @@ class TestTypelibMerge(unittest.TestCase):
|
|||
t2 = xpt.Typelib()
|
||||
# add an unresolved interface
|
||||
t2.interfaces.append(xpt.Interface("IBar", iid="44332211-6655-8877-0099-aabbccddeeff"))
|
||||
t1.merge(t2)
|
||||
t3 = xpt.xpt_link([t1, t2])
|
||||
|
||||
self.assertEqual(2, len(t1.interfaces))
|
||||
self.assertEqual(2, len(t3.interfaces))
|
||||
# Interfaces should wind up sorted
|
||||
self.assertEqual("IFoo", t1.interfaces[0].name)
|
||||
self.assertEqual("IBar", t1.interfaces[1].name)
|
||||
self.assertEqual("IFoo", t3.interfaces[0].name)
|
||||
self.assertEqual("IBar", t3.interfaces[1].name)
|
||||
|
||||
def test_mergeConflict(self):
|
||||
"""
|
||||
|
@ -425,7 +425,7 @@ class TestTypelibMerge(unittest.TestCase):
|
|||
t2 = xpt.Typelib()
|
||||
# add an unresolved interface, same name different IID
|
||||
t2.interfaces.append(xpt.Interface("IFoo", iid="44332211-6655-8877-0099-aabbccddeeff"))
|
||||
self.assertRaises(xpt.DataError, t1.merge, t2)
|
||||
self.assertRaises(xpt.DataError, xpt.xpt_link, [t1, t2])
|
||||
|
||||
# Same IIDs, different names
|
||||
t1 = xpt.Typelib()
|
||||
|
@ -434,7 +434,7 @@ class TestTypelibMerge(unittest.TestCase):
|
|||
t2 = xpt.Typelib()
|
||||
# add an unresolved interface, same IID different name
|
||||
t2.interfaces.append(xpt.Interface("IBar", iid="11223344-5566-7788-9900-aabbccddeeff"))
|
||||
self.assertRaises(xpt.DataError, t1.merge, t2)
|
||||
self.assertRaises(xpt.DataError, xpt.xpt_link, [t1, t2])
|
||||
|
||||
def test_mergeUnresolvedIID(self):
|
||||
"""
|
||||
|
@ -450,11 +450,11 @@ class TestTypelibMerge(unittest.TestCase):
|
|||
t2 = xpt.Typelib()
|
||||
# add an unresolved interface, no IID
|
||||
t2.interfaces.append(xpt.Interface("IFoo"))
|
||||
t1.merge(t2)
|
||||
t3 = xpt.xpt_link([t1, t2])
|
||||
|
||||
self.assertEqual(1, len(t1.interfaces))
|
||||
self.assertEqual("IFoo", t1.interfaces[0].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t1.interfaces[0].iid)
|
||||
self.assertEqual(1, len(t3.interfaces))
|
||||
self.assertEqual("IFoo", t3.interfaces[0].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t3.interfaces[0].iid)
|
||||
# Unresolved in both, but t2 has an IID value
|
||||
t1 = xpt.Typelib()
|
||||
# add an unresolved interface, no IID
|
||||
|
@ -462,11 +462,11 @@ class TestTypelibMerge(unittest.TestCase):
|
|||
t2 = xpt.Typelib()
|
||||
# add an unresolved interface with a valid IID
|
||||
t2.interfaces.append(xpt.Interface("IFoo", iid="11223344-5566-7788-9900-aabbccddeeff"))
|
||||
t1.merge(t2)
|
||||
t3 = xpt.xpt_link([t1, t2])
|
||||
|
||||
self.assertEqual(1, len(t1.interfaces))
|
||||
self.assertEqual("IFoo", t1.interfaces[0].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t1.interfaces[0].iid)
|
||||
self.assertEqual(1, len(t3.interfaces))
|
||||
self.assertEqual("IFoo", t3.interfaces[0].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t3.interfaces[0].iid)
|
||||
|
||||
def test_mergeResolvedUnresolved(self):
|
||||
"""
|
||||
|
@ -486,14 +486,14 @@ class TestTypelibMerge(unittest.TestCase):
|
|||
m = xpt.Method("Bar", p)
|
||||
t2.interfaces.append(xpt.Interface("IFoo", iid="11223344-5566-7788-9900-aabbccddeeff",
|
||||
methods=[m]))
|
||||
t1.merge(t2)
|
||||
t3 = xpt.xpt_link([t1, t2])
|
||||
|
||||
self.assertEqual(1, len(t1.interfaces))
|
||||
self.assertEqual("IFoo", t1.interfaces[0].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t1.interfaces[0].iid)
|
||||
self.assert_(t1.interfaces[0].resolved)
|
||||
self.assertEqual(1, len(t1.interfaces[0].methods))
|
||||
self.assertEqual("Bar", t1.interfaces[0].methods[0].name)
|
||||
self.assertEqual(1, len(t3.interfaces))
|
||||
self.assertEqual("IFoo", t3.interfaces[0].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t3.interfaces[0].iid)
|
||||
self.assert_(t3.interfaces[0].resolved)
|
||||
self.assertEqual(1, len(t3.interfaces[0].methods))
|
||||
self.assertEqual("Bar", t3.interfaces[0].methods[0].name)
|
||||
|
||||
# t1 has a resolved interface, t2 has an unresolved version
|
||||
t1 = xpt.Typelib()
|
||||
|
@ -505,14 +505,14 @@ class TestTypelibMerge(unittest.TestCase):
|
|||
t2 = xpt.Typelib()
|
||||
# add an unresolved interface
|
||||
t2.interfaces.append(xpt.Interface("IFoo"))
|
||||
t1.merge(t2)
|
||||
t3 = xpt.xpt_link([t1, t2])
|
||||
|
||||
self.assertEqual(1, len(t1.interfaces))
|
||||
self.assertEqual("IFoo", t1.interfaces[0].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t1.interfaces[0].iid)
|
||||
self.assert_(t1.interfaces[0].resolved)
|
||||
self.assertEqual(1, len(t1.interfaces[0].methods))
|
||||
self.assertEqual("Bar", t1.interfaces[0].methods[0].name)
|
||||
self.assertEqual(1, len(t3.interfaces))
|
||||
self.assertEqual("IFoo", t3.interfaces[0].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t3.interfaces[0].iid)
|
||||
self.assert_(t3.interfaces[0].resolved)
|
||||
self.assertEqual(1, len(t3.interfaces[0].methods))
|
||||
self.assertEqual("Bar", t3.interfaces[0].methods[0].name)
|
||||
|
||||
def test_mergeReplaceParents(self):
|
||||
"""
|
||||
|
@ -536,17 +536,17 @@ class TestTypelibMerge(unittest.TestCase):
|
|||
m = xpt.Method("Bar", p)
|
||||
t2.interfaces.append(xpt.Interface("IFoo", iid="11223344-5566-7788-9900-aabbccddeeff",
|
||||
methods=[m]))
|
||||
t1.merge(t2)
|
||||
t3 = xpt.xpt_link([t1, t2])
|
||||
|
||||
self.assertEqual(2, len(t1.interfaces))
|
||||
self.assertEqual("IChild", t1.interfaces[0].name)
|
||||
self.assertEqual("11111111-1111-1111-1111-111111111111", t1.interfaces[0].iid)
|
||||
self.assertEqual("IFoo", t1.interfaces[1].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t1.interfaces[1].iid)
|
||||
self.assert_(t1.interfaces[0].resolved)
|
||||
self.assertEqual(2, len(t3.interfaces))
|
||||
self.assertEqual("IChild", t3.interfaces[0].name)
|
||||
self.assertEqual("11111111-1111-1111-1111-111111111111", t3.interfaces[0].iid)
|
||||
self.assertEqual("IFoo", t3.interfaces[1].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t3.interfaces[1].iid)
|
||||
self.assert_(t3.interfaces[0].resolved)
|
||||
# Ensure that IChild's parent has been updated
|
||||
self.assertEqual(t1.interfaces[1], t1.interfaces[0].parent)
|
||||
self.assert_(t1.interfaces[0].parent.resolved)
|
||||
self.assertEqual(t3.interfaces[1], t3.interfaces[0].parent)
|
||||
self.assert_(t3.interfaces[0].parent.resolved)
|
||||
|
||||
# t1 has a resolved interface, t2 has an unresolved version,
|
||||
# but t2 also has another interface whose parent is the unresolved
|
||||
|
@ -564,17 +564,17 @@ class TestTypelibMerge(unittest.TestCase):
|
|||
# add a child of the unresolved interface
|
||||
t2.interfaces.append(xpt.Interface("IChild", iid="11111111-1111-1111-1111-111111111111",
|
||||
resolved=True, parent=pi))
|
||||
t1.merge(t2)
|
||||
t3 = xpt.xpt_link([t1, t2])
|
||||
|
||||
self.assertEqual(2, len(t1.interfaces))
|
||||
self.assertEqual("IChild", t1.interfaces[0].name)
|
||||
self.assertEqual("11111111-1111-1111-1111-111111111111", t1.interfaces[0].iid)
|
||||
self.assertEqual("IFoo", t1.interfaces[1].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t1.interfaces[1].iid)
|
||||
self.assert_(t1.interfaces[0].resolved)
|
||||
self.assertEqual(2, len(t3.interfaces))
|
||||
self.assertEqual("IChild", t3.interfaces[0].name)
|
||||
self.assertEqual("11111111-1111-1111-1111-111111111111", t3.interfaces[0].iid)
|
||||
self.assertEqual("IFoo", t3.interfaces[1].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t3.interfaces[1].iid)
|
||||
self.assert_(t3.interfaces[0].resolved)
|
||||
# Ensure that IChild's parent has been updated
|
||||
self.assertEqual(t1.interfaces[1], t1.interfaces[0].parent)
|
||||
self.assert_(t1.interfaces[0].parent.resolved)
|
||||
self.assertEqual(t3.interfaces[1], t3.interfaces[0].parent)
|
||||
self.assert_(t3.interfaces[0].parent.resolved)
|
||||
|
||||
def test_mergeReplaceRetval(self):
|
||||
"""
|
||||
|
@ -601,19 +601,19 @@ class TestTypelibMerge(unittest.TestCase):
|
|||
m = xpt.Method("Bar", p)
|
||||
t2.interfaces.append(xpt.Interface("IFoo", iid="11223344-5566-7788-9900-aabbccddeeff",
|
||||
methods=[m]))
|
||||
t1.merge(t2)
|
||||
t3 = xpt.xpt_link([t1, t2])
|
||||
|
||||
self.assertEqual(2, len(t1.interfaces))
|
||||
self.assertEqual("IRetval", t1.interfaces[0].name)
|
||||
self.assertEqual("11111111-1111-1111-1111-111111111111", t1.interfaces[0].iid)
|
||||
self.assertEqual("IFoo", t1.interfaces[1].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t1.interfaces[1].iid)
|
||||
self.assert_(t1.interfaces[1].resolved)
|
||||
self.assertEqual(2, len(t3.interfaces))
|
||||
self.assertEqual("IRetval", t3.interfaces[0].name)
|
||||
self.assertEqual("11111111-1111-1111-1111-111111111111", t3.interfaces[0].iid)
|
||||
self.assertEqual("IFoo", t3.interfaces[1].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t3.interfaces[1].iid)
|
||||
self.assert_(t3.interfaces[1].resolved)
|
||||
# Ensure that IRetval's method's return value type has been updated.
|
||||
self.assertEqual(1, len(t1.interfaces[0].methods))
|
||||
self.assert_(t1.interfaces[0].methods[0].result.type.iface.resolved)
|
||||
self.assertEqual(t1.interfaces[1],
|
||||
t1.interfaces[0].methods[0].result.type.iface)
|
||||
self.assertEqual(1, len(t3.interfaces[0].methods))
|
||||
self.assert_(t3.interfaces[0].methods[0].result.type.iface.resolved)
|
||||
self.assertEqual(t3.interfaces[1],
|
||||
t3.interfaces[0].methods[0].result.type.iface)
|
||||
|
||||
# t1 has a resolved interface. t2 has an unresolved version and
|
||||
# an interface that uses the unresolved interface as a return value
|
||||
|
@ -634,19 +634,19 @@ class TestTypelibMerge(unittest.TestCase):
|
|||
m = xpt.Method("ReturnIface", p)
|
||||
t2.interfaces.append(xpt.Interface("IRetval", iid="11111111-1111-1111-1111-111111111111",
|
||||
methods=[m]))
|
||||
t1.merge(t2)
|
||||
t3 = xpt.xpt_link([t1, t2])
|
||||
|
||||
self.assertEqual(2, len(t1.interfaces))
|
||||
self.assertEqual("IRetval", t1.interfaces[0].name)
|
||||
self.assertEqual("11111111-1111-1111-1111-111111111111", t1.interfaces[0].iid)
|
||||
self.assertEqual("IFoo", t1.interfaces[1].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t1.interfaces[1].iid)
|
||||
self.assert_(t1.interfaces[1].resolved)
|
||||
self.assertEqual(2, len(t3.interfaces))
|
||||
self.assertEqual("IRetval", t3.interfaces[0].name)
|
||||
self.assertEqual("11111111-1111-1111-1111-111111111111", t3.interfaces[0].iid)
|
||||
self.assertEqual("IFoo", t3.interfaces[1].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t3.interfaces[1].iid)
|
||||
self.assert_(t3.interfaces[1].resolved)
|
||||
# Ensure that IRetval's method's return value type has been updated.
|
||||
self.assertEqual(1, len(t1.interfaces[0].methods))
|
||||
self.assert_(t1.interfaces[0].methods[0].result.type.iface.resolved)
|
||||
self.assertEqual(t1.interfaces[1],
|
||||
t1.interfaces[0].methods[0].result.type.iface)
|
||||
self.assertEqual(1, len(t3.interfaces[0].methods))
|
||||
self.assert_(t3.interfaces[0].methods[0].result.type.iface.resolved)
|
||||
self.assertEqual(t3.interfaces[1],
|
||||
t3.interfaces[0].methods[0].result.type.iface)
|
||||
|
||||
def test_mergeReplaceParams(self):
|
||||
"""
|
||||
|
@ -673,19 +673,19 @@ class TestTypelibMerge(unittest.TestCase):
|
|||
m = xpt.Method("Bar", vp)
|
||||
t2.interfaces.append(xpt.Interface("IFoo", iid="11223344-5566-7788-9900-aabbccddeeff",
|
||||
methods=[m]))
|
||||
t1.merge(t2)
|
||||
t3 = xpt.xpt_link([t1, t2])
|
||||
|
||||
self.assertEqual(2, len(t1.interfaces))
|
||||
self.assertEqual("IParam", t1.interfaces[0].name)
|
||||
self.assertEqual("11111111-1111-1111-1111-111111111111", t1.interfaces[0].iid)
|
||||
self.assertEqual("IFoo", t1.interfaces[1].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t1.interfaces[1].iid)
|
||||
self.assert_(t1.interfaces[1].resolved)
|
||||
self.assertEqual(2, len(t3.interfaces))
|
||||
self.assertEqual("IParam", t3.interfaces[0].name)
|
||||
self.assertEqual("11111111-1111-1111-1111-111111111111", t3.interfaces[0].iid)
|
||||
self.assertEqual("IFoo", t3.interfaces[1].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t3.interfaces[1].iid)
|
||||
self.assert_(t3.interfaces[1].resolved)
|
||||
# Ensure that IRetval's method's param type has been updated.
|
||||
self.assertEqual(1, len(t1.interfaces[0].methods))
|
||||
self.assert_(t1.interfaces[0].methods[0].params[0].type.iface.resolved)
|
||||
self.assertEqual(t1.interfaces[1],
|
||||
t1.interfaces[0].methods[0].params[0].type.iface)
|
||||
self.assertEqual(1, len(t3.interfaces[0].methods))
|
||||
self.assert_(t3.interfaces[0].methods[0].params[0].type.iface.resolved)
|
||||
self.assertEqual(t3.interfaces[1],
|
||||
t3.interfaces[0].methods[0].params[0].type.iface)
|
||||
|
||||
# t1 has a resolved interface. t2 has an unresolved version
|
||||
# and an interface that uses the unresolved interface as a
|
||||
|
@ -706,19 +706,19 @@ class TestTypelibMerge(unittest.TestCase):
|
|||
m = xpt.Method("IfaceParam", vp, params=[p])
|
||||
t2.interfaces.append(xpt.Interface("IParam", iid="11111111-1111-1111-1111-111111111111",
|
||||
methods=[m]))
|
||||
t1.merge(t2)
|
||||
t3 = xpt.xpt_link([t1, t2])
|
||||
|
||||
self.assertEqual(2, len(t1.interfaces))
|
||||
self.assertEqual("IParam", t1.interfaces[0].name)
|
||||
self.assertEqual("11111111-1111-1111-1111-111111111111", t1.interfaces[0].iid)
|
||||
self.assertEqual("IFoo", t1.interfaces[1].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t1.interfaces[1].iid)
|
||||
self.assert_(t1.interfaces[1].resolved)
|
||||
self.assertEqual(2, len(t3.interfaces))
|
||||
self.assertEqual("IParam", t3.interfaces[0].name)
|
||||
self.assertEqual("11111111-1111-1111-1111-111111111111", t3.interfaces[0].iid)
|
||||
self.assertEqual("IFoo", t3.interfaces[1].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t3.interfaces[1].iid)
|
||||
self.assert_(t3.interfaces[1].resolved)
|
||||
# Ensure that IRetval's method's param type has been updated.
|
||||
self.assertEqual(1, len(t1.interfaces[0].methods))
|
||||
self.assert_(t1.interfaces[0].methods[0].params[0].type.iface.resolved)
|
||||
self.assertEqual(t1.interfaces[1],
|
||||
t1.interfaces[0].methods[0].params[0].type.iface)
|
||||
self.assertEqual(1, len(t3.interfaces[0].methods))
|
||||
self.assert_(t3.interfaces[0].methods[0].params[0].type.iface.resolved)
|
||||
self.assertEqual(t3.interfaces[1],
|
||||
t3.interfaces[0].methods[0].params[0].type.iface)
|
||||
|
||||
|
||||
def test_mergeReplaceArrayTypeParams(self):
|
||||
|
@ -748,74 +748,19 @@ class TestTypelibMerge(unittest.TestCase):
|
|||
m = xpt.Method("Bar", vp)
|
||||
t2.interfaces.append(xpt.Interface("IFoo", iid="11223344-5566-7788-9900-aabbccddeeff",
|
||||
methods=[m]))
|
||||
t1.merge(t2)
|
||||
|
||||
self.assertEqual(2, len(t1.interfaces))
|
||||
self.assertEqual("IParam", t1.interfaces[0].name)
|
||||
self.assertEqual("11111111-1111-1111-1111-111111111111", t1.interfaces[0].iid)
|
||||
self.assertEqual("IFoo", t1.interfaces[1].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t1.interfaces[1].iid)
|
||||
self.assert_(t1.interfaces[1].resolved)
|
||||
# Ensure that IRetval's method's param type has been updated.
|
||||
self.assertEqual(1, len(t1.interfaces[0].methods))
|
||||
self.assert_(t1.interfaces[0].methods[0].params[0].type.element_type.iface.resolved)
|
||||
self.assertEqual(t1.interfaces[1],
|
||||
t1.interfaces[0].methods[0].params[0].type.element_type.iface)
|
||||
|
||||
class TestXPTLink(unittest.TestCase):
|
||||
def test_xpt_link(self):
|
||||
"""
|
||||
Test the xpt_link method.
|
||||
|
||||
"""
|
||||
t1 = xpt.Typelib()
|
||||
# add an unresolved interface
|
||||
t1.interfaces.append(xpt.Interface("IFoo"))
|
||||
f1 = StringIO()
|
||||
t1.write(f1)
|
||||
f1.seek(0)
|
||||
|
||||
t2 = xpt.Typelib()
|
||||
# add an unresolved interface
|
||||
t2.interfaces.append(xpt.Interface("IBar"))
|
||||
f2 = StringIO()
|
||||
t2.write(f2)
|
||||
f2.seek(0)
|
||||
|
||||
f3 = StringIO()
|
||||
xpt.xpt_link(f3, [f1, f2])
|
||||
f3.seek(0)
|
||||
t3 = xpt.Typelib.read(f3)
|
||||
t3 = xpt.xpt_link([t1, t2])
|
||||
|
||||
self.assertEqual(2, len(t3.interfaces))
|
||||
# Interfaces should wind up sorted
|
||||
self.assertEqual("IBar", t3.interfaces[0].name)
|
||||
self.assertEqual("IParam", t3.interfaces[0].name)
|
||||
self.assertEqual("11111111-1111-1111-1111-111111111111", t3.interfaces[0].iid)
|
||||
self.assertEqual("IFoo", t3.interfaces[1].name)
|
||||
|
||||
# Add some IID values
|
||||
t1 = xpt.Typelib()
|
||||
# add an unresolved interface
|
||||
t1.interfaces.append(xpt.Interface("IFoo", iid="11223344-5566-7788-9900-aabbccddeeff"))
|
||||
f1 = StringIO()
|
||||
t1.write(f1)
|
||||
f1.seek(0)
|
||||
|
||||
t2 = xpt.Typelib()
|
||||
# add an unresolved interface
|
||||
t2.interfaces.append(xpt.Interface("IBar", iid="44332211-6655-8877-0099-aabbccddeeff"))
|
||||
f2 = StringIO()
|
||||
t2.write(f2)
|
||||
f2.seek(0)
|
||||
|
||||
f3 = StringIO()
|
||||
xpt.xpt_link(f3, [f1, f2])
|
||||
f3.seek(0)
|
||||
t3 = xpt.Typelib.read(f3)
|
||||
|
||||
self.assertEqual(2, len(t3.interfaces))
|
||||
# Interfaces should wind up sorted
|
||||
self.assertEqual("IFoo", t3.interfaces[0].name)
|
||||
self.assertEqual("IBar", t3.interfaces[1].name)
|
||||
self.assertEqual("11223344-5566-7788-9900-aabbccddeeff", t3.interfaces[1].iid)
|
||||
self.assert_(t3.interfaces[1].resolved)
|
||||
# Ensure that IRetval's method's param type has been updated.
|
||||
self.assertEqual(1, len(t3.interfaces[0].methods))
|
||||
self.assert_(t3.interfaces[0].methods[0].params[0].type.element_type.iface.resolved)
|
||||
self.assertEqual(t3.interfaces[1],
|
||||
t3.interfaces[0].methods[0].params[0].type.element_type.iface)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -68,6 +68,7 @@ InterfaceType() - construct a new object representing a type that
|
|||
from __future__ import with_statement
|
||||
import os, sys
|
||||
import struct
|
||||
import operator
|
||||
|
||||
# header magic
|
||||
XPT_MAGIC = "XPCOM\nTypeLib\r\n\x1a"
|
||||
|
@ -878,6 +879,9 @@ class Interface(object):
|
|||
def __str__(self):
|
||||
return "Interface(name='%s', iid='%s')" % (self.name, self.iid)
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.name, self.iid))
|
||||
|
||||
def __cmp__(self, other):
|
||||
c = cmp(self.iid, other.iid)
|
||||
if c != 0:
|
||||
|
@ -1186,94 +1190,6 @@ class Typelib(object):
|
|||
else:
|
||||
self.writefd(output_file)
|
||||
|
||||
def merge(self, other, sanitycheck=True):
|
||||
"""
|
||||
Merge the contents of Typelib |other| into this typelib.
|
||||
If |sanitycheck| is False, don't sort the interface table
|
||||
after merging.
|
||||
|
||||
"""
|
||||
# This will be a list of (replaced interface, replaced with)
|
||||
# containing interfaces that were replaced with interfaces from
|
||||
# another typelib, and the interface that replaced them.
|
||||
merged_interfaces = []
|
||||
for i in other.interfaces:
|
||||
if i in self.interfaces:
|
||||
continue
|
||||
# See if there's a copy of this interface with different
|
||||
# resolved status or IID value.
|
||||
merged = False
|
||||
for j in self.interfaces:
|
||||
if i.name == j.name:
|
||||
if i.resolved != j.resolved:
|
||||
# prefer resolved interfaces over unresolved
|
||||
if j.resolved:
|
||||
# keep j
|
||||
merged_interfaces.append((i, j))
|
||||
merged = True
|
||||
# Fixup will happen after processing all interfaces.
|
||||
else:
|
||||
# replace j with i
|
||||
merged_interfaces.append((j, i))
|
||||
merged = True
|
||||
self.interfaces[self.interfaces.index(j)] = i
|
||||
elif i.iid != j.iid:
|
||||
# Prefer unresolved interfaces with valid IIDs
|
||||
if j.iid == Interface.UNRESOLVED_IID:
|
||||
# replace j with i
|
||||
merged_interfaces.append((j, i))
|
||||
merged = True
|
||||
self.interfaces[self.interfaces.index(j)] = i
|
||||
elif i.iid == Interface.UNRESOLVED_IID:
|
||||
# keep j
|
||||
merged_interfaces.append((i, j))
|
||||
merged = True
|
||||
# Fixup will happen after processing all interfaces.
|
||||
else:
|
||||
# Same name but different IIDs: raise an exception.
|
||||
# self.* is the (target) Typelib being merged into,
|
||||
# not the one which j.iid was from.
|
||||
raise DataError, \
|
||||
"Typelibs contain definitions of interface %s" \
|
||||
" with different IIDs (%s (%s) vs %s (%s))!" % \
|
||||
(i.name, i.iid, i.xpt_filename or other.filename, \
|
||||
j.iid, j.xpt_filename or self.filename)
|
||||
elif i.iid == j.iid and i.iid != Interface.UNRESOLVED_IID:
|
||||
# Same IID but different names: raise an exception.
|
||||
# self.* is the (target) Typelib being merged into,
|
||||
# not the one which j.name was from.
|
||||
raise DataError, \
|
||||
"Typelibs contain definitions of interface %s" \
|
||||
" with different names (%s (%s) vs %s (%s))!" % \
|
||||
(i.iid, i.name, i.xpt_filename or other.filename, \
|
||||
j.name, j.xpt_filename or self.filename)
|
||||
if not merged:
|
||||
# No partially matching interfaces, so just take this interface
|
||||
self.interfaces.append(i)
|
||||
|
||||
# Now fixup any merged interfaces
|
||||
def checkType(t, replaced_from, replaced_to):
|
||||
if isinstance(t, InterfaceType) and t.iface == replaced_from:
|
||||
t.iface = replaced_to
|
||||
elif isinstance(t, ArrayType) and \
|
||||
isinstance(t.element_type, InterfaceType) and \
|
||||
t.element_type.iface == replaced_from:
|
||||
t.element_type.iface = replaced_to
|
||||
|
||||
for replaced_from, replaced_to in merged_interfaces:
|
||||
for i in self.interfaces:
|
||||
# Replace parent references
|
||||
if i.parent is not None and i.parent == replaced_from:
|
||||
i.parent = replaced_to
|
||||
for m in i.methods:
|
||||
# Replace InterfaceType params and return values
|
||||
checkType(m.result.type, replaced_from, replaced_to)
|
||||
for p in m.params:
|
||||
checkType(p.type, replaced_from, replaced_to)
|
||||
if sanitycheck:
|
||||
self._sanityCheck()
|
||||
#TODO: do we care about annotations? probably not
|
||||
|
||||
def dump(self, out):
|
||||
"""
|
||||
Print a human-readable listing of the contents of this typelib
|
||||
|
@ -1335,21 +1251,126 @@ def xpt_dump(file):
|
|||
t = Typelib.read(file)
|
||||
t.dump(sys.stdout)
|
||||
|
||||
def xpt_link(dest, inputs):
|
||||
def xpt_link(inputs):
|
||||
"""
|
||||
Link all of the xpt files in |inputs| together and write the
|
||||
result to |dest|. All parameters may be filenames or file-like objects.
|
||||
Link all of the xpt files in |inputs| together and return the result
|
||||
as a Typelib object. All entries in inputs may be filenames or
|
||||
file-like objects.
|
||||
|
||||
"""
|
||||
def read_input(i):
|
||||
if isinstance(i, Typelib):
|
||||
return i
|
||||
return Typelib.read(i)
|
||||
|
||||
if not inputs:
|
||||
print >>sys.stderr, "Usage: xpt_link <destination file> <input files>"
|
||||
return
|
||||
t1 = Typelib.read(inputs[0])
|
||||
for f in inputs[1:]:
|
||||
t2 = Typelib.read(f)
|
||||
# write will call sanitycheck, so skip it here.
|
||||
t1.merge(t2, sanitycheck=False)
|
||||
t1.write(dest)
|
||||
return None
|
||||
# This is the aggregate list of interfaces.
|
||||
interfaces = []
|
||||
# This will be a dict of replaced interface -> replaced with
|
||||
# containing interfaces that were replaced with interfaces from
|
||||
# another typelib, and the interface that replaced them.
|
||||
merged_interfaces = {}
|
||||
for f in inputs:
|
||||
t = read_input(f)
|
||||
interfaces.extend(t.interfaces)
|
||||
# Sort interfaces by name so we can merge adjacent duplicates
|
||||
interfaces.sort(key=operator.attrgetter('name'))
|
||||
|
||||
Result = enum('Equal', # Interfaces the same, doesn't matter
|
||||
'NotEqual', # Interfaces differ, keep both
|
||||
'KeepFirst', # Replace second interface with first
|
||||
'KeepSecond')# Replace first interface with second
|
||||
|
||||
def compare(i, j):
|
||||
"""
|
||||
Compare two interfaces, determine if they're equal or
|
||||
completely different, or should be merged (and indicate which
|
||||
one to keep in that case).
|
||||
|
||||
"""
|
||||
if i == j:
|
||||
# Arbitrary, just pick one
|
||||
return Result.Equal
|
||||
if i.name != j.name:
|
||||
if i.iid == j.iid and i.iid != Interface.UNRESOLVED_IID:
|
||||
# Same IID but different names: raise an exception.
|
||||
raise DataError, \
|
||||
"Typelibs contain definitions of interface %s" \
|
||||
" with different names (%s (%s) vs %s (%s))!" % \
|
||||
(i.iid, i.name, i.xpt_filename, j.name, j.xpt_filename)
|
||||
# Otherwise just different interfaces.
|
||||
return Result.NotEqual
|
||||
# Interfaces have the same name, so either they need to be merged
|
||||
# or there's a data error. Sort out which one to keep
|
||||
if i.resolved != j.resolved:
|
||||
# prefer resolved interfaces over unresolved
|
||||
if j.resolved:
|
||||
assert i.iid == j.iid or i.iid == Interface.UNRESOLVED_IID
|
||||
# keep j
|
||||
return Result.KeepSecond
|
||||
else:
|
||||
assert i.iid == j.iid or j.iid == Interface.UNRESOLVED_IID
|
||||
# replace j with i
|
||||
return Result.KeepFirst
|
||||
elif i.iid != j.iid:
|
||||
# Prefer unresolved interfaces with valid IIDs
|
||||
if j.iid == Interface.UNRESOLVED_IID:
|
||||
# replace j with i
|
||||
assert not j.resolved
|
||||
return Result.KeepFirst
|
||||
elif i.iid == Interface.UNRESOLVED_IID:
|
||||
# keep j
|
||||
assert not i.resolved
|
||||
return Result.KeepSecond
|
||||
else:
|
||||
# Same name but different IIDs: raise an exception.
|
||||
raise DataError, \
|
||||
"Typelibs contain definitions of interface %s" \
|
||||
" with different IIDs (%s (%s) vs %s (%s))!" % \
|
||||
(i.name, i.iid, i.xpt_filename, \
|
||||
j.iid, j.xpt_filename)
|
||||
raise DataError, "No idea what happened here: %s:%s (%s), %s:%s (%s)" % \
|
||||
(i.name, i.iid, i.xpt_filename, j.name, j.iid, j.xpt_filename)
|
||||
|
||||
# Compare interfaces pairwise to find duplicates that should be merged.
|
||||
i = 1
|
||||
while i < len(interfaces):
|
||||
res = compare(interfaces[i-1], interfaces[i])
|
||||
if res == Result.NotEqual:
|
||||
i += 1
|
||||
elif res == Result.Equal:
|
||||
# Need to drop one but it doesn't matter which
|
||||
del interfaces[i]
|
||||
elif res == Result.KeepFirst:
|
||||
merged_interfaces[interfaces[i]] = interfaces[i-1]
|
||||
del interfaces[i]
|
||||
elif res == Result.KeepSecond:
|
||||
merged_interfaces[interfaces[i-1]] = interfaces[i]
|
||||
del interfaces[i-1]
|
||||
|
||||
# Now fixup any merged interfaces
|
||||
def checkType(t):
|
||||
if isinstance(t, InterfaceType) and t.iface in merged_interfaces:
|
||||
t.iface = merged_interfaces[t.iface]
|
||||
elif isinstance(t, ArrayType) and \
|
||||
isinstance(t.element_type, InterfaceType) and \
|
||||
t.element_type.iface in merged_interfaces:
|
||||
t.element_type.iface = merged_interfaces[t.element_type.iface]
|
||||
|
||||
for i in interfaces:
|
||||
# Replace parent references
|
||||
if i.parent in merged_interfaces:
|
||||
i.parent = merged_interfaces[i.parent]
|
||||
for m in i.methods:
|
||||
# Replace InterfaceType params and return values
|
||||
checkType(m.result.type)
|
||||
for p in m.params:
|
||||
checkType(p.type)
|
||||
# Re-sort interfaces (by IID)
|
||||
interfaces.sort()
|
||||
return Typelib(interfaces=interfaces)
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) < 3:
|
||||
|
@ -1358,4 +1379,5 @@ if __name__ == '__main__':
|
|||
if sys.argv[1] == 'dump':
|
||||
xpt_dump(sys.argv[2])
|
||||
elif sys.argv[1] == 'link':
|
||||
xpt_link(sys.argv[2], sys.argv[3:])
|
||||
xpt_link(sys.argv[3:]).write(sys.argv[2])
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче