def test_set_adaptation_manager(self): ex = self.examples adaptation_manager = AdaptationManager() # UKStandard->EUStandard. adaptation_manager.register_factory(factory=ex.UKStandardToEUStandard, from_protocol=ex.UKStandard, to_protocol=ex.EUStandard) # Create a UKPlug. uk_plug = ex.UKPlug() set_global_adaptation_manager(adaptation_manager) global_adaptation_manager = get_global_adaptation_manager() eu_plug = global_adaptation_manager.adapt(uk_plug, ex.EUStandard) self.assertIsNotNone(eu_plug) self.assertIsInstance(eu_plug, ex.UKStandardToEUStandard)
def test_set_adaptation_manager(self): ex = self.examples adaptation_manager = AdaptationManager() # UKStandard->EUStandard. adaptation_manager.register_factory( factory = ex.UKStandardToEUStandard, from_protocol = ex.UKStandard, to_protocol = ex.EUStandard ) # Create a UKPlug. uk_plug = ex.UKPlug() set_global_adaptation_manager(adaptation_manager) global_adaptation_manager = get_global_adaptation_manager() eu_plug = global_adaptation_manager.adapt(uk_plug, ex.EUStandard) self.assertIsNotNone(eu_plug) self.assertIsInstance(eu_plug, ex.UKStandardToEUStandard)
def setUp(self): """ Prepares the test fixture before each test method is called. """ self.adaptation_manager = AdaptationManager() return
class TestCachedAdapterFactory(unittest.TestCase): """ Test the cached adapter factory. """ examples = traits.adaptation.tests.interface_examples #### 'TestCase' protocol ################################################## def setUp(self): """ Prepares the test fixture before each test method is called. """ self.adaptation_manager = AdaptationManager() return def tearDown(self): """ Called immediately after each test method has been called. """ return #### Tests ################################################################# def test_cached_adapters(self): ex = self.examples factory = CachedAdapterFactory(factory=ex.EditorToIPrintable) self.adaptation_manager.register_factory( factory = factory, from_protocol = ex.Editor, to_protocol = ex.IPrintable ) editor = ex.Editor() adapter_1 = self.adaptation_manager.adapt(editor, ex.IPrintable) self.assertIsNotNone(adapter_1) self.assertIs(type(adapter_1), ex.EditorToIPrintable) adapter_2 = self.adaptation_manager.adapt(editor, ex.IPrintable) self.assertIsNotNone(adapter_2) self.assertIs(type(adapter_2), ex.EditorToIPrintable) self.assertIs(adapter_1, adapter_2) return @unittest.skip("Cache cleaning is broken") def test_cached_adapters_should_be_cleaned_up(self): ex = self.examples factory = CachedAdapterFactory(factory=ex.EditorToIPrintable) self.adaptation_manager.register_factory( factory = factory, from_protocol = ex.Editor, to_protocol = ex.IPrintable ) editor = ex.Editor() adapter_1 = self.adaptation_manager.adapt(editor, ex.IPrintable) self.assertIsNotNone(adapter_1) self.assertIs(type(adapter_1), ex.EditorToIPrintable) del adapter_1 del editor self.assertTrue(factory.is_empty) return def test_cached_adapters_with_lazy_loaded_factory(self): LAZY_EXAMPLES = 'traits.adaptation.tests.lazy_examples' if LAZY_EXAMPLES in sys.modules: del sys.modules[LAZY_EXAMPLES] factory = CachedAdapterFactory(factory=LAZY_EXAMPLES + '.IBarToIFoo') self.adaptation_manager.register_factory( factory = factory, from_protocol = LAZY_EXAMPLES + '.IBar', to_protocol = LAZY_EXAMPLES + '.IFoo', ) self.assertNotIn(LAZY_EXAMPLES, sys.modules) # The *actual* factory is loaded on-demand. bogus = factory.factory self.assertIn(LAZY_EXAMPLES, sys.modules) return @unittest.skip("Cache cleaning is broken") def test_cached_adapter_that_was_garbage_collected(self): ex = self.examples factory = CachedAdapterFactory(factory=ex.EditorToIPrintable) self.adaptation_manager.register_factory( factory = factory, from_protocol = ex.Editor, to_protocol = ex.IPrintable ) editor = ex.Editor() adapter_1 = self.adaptation_manager.adapt(editor, ex.IPrintable) self.assertIs(type(adapter_1), ex.EditorToIPrintable) adapter_1.marker = 'marker' del adapter_1 adapter_2 = self.adaptation_manager.adapt(editor, ex.IPrintable) self.assertIsNotNone(adapter_2) self.assertTrue(hasattr(adapter_2, 'marker')) del adapter_2 del editor self.assertTrue(factory.is_empty)
class TestAdaptationManagerWithABC(unittest.TestCase): """ Test the adaptation manager. """ #: Class attribute pointing at the module containing the example data examples = traits.adaptation.tests.abc_examples #### 'TestCase' protocol ################################################## def setUp(self): """ Prepares the test fixture before each test method is called. """ self.adaptation_manager = AdaptationManager() return def tearDown(self): """ Called immediately after each test method has been called. """ return #### Tests ################################################################ def test_no_adapter_required(self): ex = self.examples plug = ex.UKPlug() # Try to adapt it to its own concrete type. uk_plug = self.adaptation_manager.adapt(plug, ex.UKPlug) # The adaptation manager should simply return the same object. self.assertIs(uk_plug, plug) # Try to adapt it to an ABC that is registered for its type. uk_plug = self.adaptation_manager.adapt(plug, ex.UKStandard) # The adaptation manager should simply return the same object. self.assertIs(uk_plug, plug) return def test_no_adapter_available(self): ex = self.examples plug = ex.UKPlug() # Try to adapt it to a concrete type. eu_plug = self.adaptation_manager.adapt(plug, ex.EUPlug, None) # There should be no way to adapt a UKPlug to a EUPlug. self.assertEqual(eu_plug, None) # Try to adapt it to an ABC. eu_plug = self.adaptation_manager.adapt(plug, ex.EUStandard, None) # There should be no way to adapt a UKPlug to a EUPlug. self.assertEqual(eu_plug, None) return def test_one_step_adaptation(self): ex = self.examples # UKStandard->EUStandard. self.adaptation_manager.register_factory( factory=ex.UKStandardToEUStandard, from_protocol=ex.UKStandard, to_protocol=ex.EUStandard, ) plug = ex.UKPlug() # Adapt it to an ABC. eu_plug = self.adaptation_manager.adapt(plug, ex.EUStandard) self.assertIsNotNone(eu_plug) self.assertIsInstance(eu_plug, ex.UKStandardToEUStandard) # We shouldn't be able to adapt it to a *concrete* 'EUPlug' though. eu_plug = self.adaptation_manager.adapt(plug, ex.EUPlug, None) self.assertIsNone(eu_plug) return def test_adapter_chaining(self): ex = self.examples # UKStandard->EUStandard. self.adaptation_manager.register_factory( factory=ex.UKStandardToEUStandard, from_protocol=ex.UKStandard, to_protocol=ex.EUStandard, ) # EUStandard->JapanStandard. self.adaptation_manager.register_factory( factory=ex.EUStandardToJapanStandard, from_protocol=ex.EUStandard, to_protocol=ex.JapanStandard, ) # Create a UKPlug. uk_plug = ex.UKPlug() # Adapt it to a JapanStandard via the chain. japan_plug = self.adaptation_manager.adapt(uk_plug, ex.JapanStandard) self.assertIsNotNone(japan_plug) self.assertIsInstance(japan_plug, ex.EUStandardToJapanStandard) self.assertIs(japan_plug.adaptee.adaptee, uk_plug) return def test_multiple_paths_unambiguous(self): ex = self.examples # UKStandard->EUStandard. self.adaptation_manager.register_factory( factory=ex.UKStandardToEUStandard, from_protocol=ex.UKStandard, to_protocol=ex.EUStandard, ) # EUStandard->JapanStandard. self.adaptation_manager.register_factory( factory=ex.EUStandardToJapanStandard, from_protocol=ex.EUStandard, to_protocol=ex.JapanStandard, ) # JapanStandard->IraqStandard. self.adaptation_manager.register_factory( factory=ex.JapanStandardToIraqStandard, from_protocol=ex.JapanStandard, to_protocol=ex.IraqStandard, ) # EUStandard->IraqStandard. self.adaptation_manager.register_factory( factory=ex.EUStandardToIraqStandard, from_protocol=ex.EUStandard, to_protocol=ex.IraqStandard, ) # Create a UKPlug. uk_plug = ex.UKPlug() # Adapt it to a IraqStandard via the chain. iraq_plug = self.adaptation_manager.adapt(uk_plug, ex.IraqStandard) self.assertIsNotNone(iraq_plug) self.assertIsInstance(iraq_plug, ex.EUStandardToIraqStandard) self.assertIs(iraq_plug.adaptee.adaptee, uk_plug) return def test_multiple_paths_ambiguous(self): ex = self.examples # UKStandard->EUStandard. self.adaptation_manager.register_factory( factory=ex.UKStandardToEUStandard, from_protocol=ex.UKStandard, to_protocol=ex.EUStandard, ) # UKStandard->JapanStandard. self.adaptation_manager.register_factory( factory=ex.UKStandardToJapanStandard, from_protocol=ex.UKStandard, to_protocol=ex.JapanStandard, ) # JapanStandard->IraqStandard. self.adaptation_manager.register_factory( factory=ex.JapanStandardToIraqStandard, from_protocol=ex.JapanStandard, to_protocol=ex.IraqStandard, ) # EUStandard->IraqStandard. self.adaptation_manager.register_factory( factory=ex.EUStandardToIraqStandard, from_protocol=ex.EUStandard, to_protocol=ex.IraqStandard, ) # Create a UKPlug. uk_plug = ex.UKPlug() # Adapt it to a IraqStandard via the chain. iraq_plug = self.adaptation_manager.adapt(uk_plug, ex.IraqStandard) self.assertIsNotNone(iraq_plug) self.assertIn( type(iraq_plug), [ex.EUStandardToIraqStandard, ex.JapanStandardToIraqStandard], ) self.assertIs(iraq_plug.adaptee.adaptee, uk_plug) return def test_conditional_adaptation(self): ex = self.examples # TravelPlug->EUStandard. def travel_plug_to_eu_standard(adaptee): if adaptee.mode == "Europe": return ex.TravelPlugToEUStandard(adaptee=adaptee) else: return None self.adaptation_manager.register_factory( factory=travel_plug_to_eu_standard, from_protocol=ex.TravelPlug, to_protocol=ex.EUStandard, ) # Create a TravelPlug. travel_plug = ex.TravelPlug(mode="Europe") # Adapt it to a EUStandard. eu_plug = self.adaptation_manager.adapt(travel_plug, ex.EUStandard) self.assertIsNotNone(eu_plug) self.assertIsInstance(eu_plug, ex.TravelPlugToEUStandard) # Create a TravelPlug. travel_plug = ex.TravelPlug(mode="Asia") # Adapt it to a EUStandard. eu_plug = self.adaptation_manager.adapt( travel_plug, ex.EUStandard, None ) self.assertIsNone(eu_plug) return def test_spillover_adaptation_behavior(self): ex = self.examples # FileType->IEditor. self.adaptation_manager.register_factory( factory=ex.FileTypeToIEditor, from_protocol=ex.FileType, to_protocol=ex.IEditor, ) # Meanwhile, in a plugin far, far away ... # IScriptable->IPrintable. self.adaptation_manager.register_factory( factory=ex.IScriptableToIUndoable, from_protocol=ex.IScriptable, to_protocol=ex.IUndoable, ) # Create a file type. file_type = ex.FileType() # Try to adapt to IPrintable: since we did not define an adapter # chain that goes from FileType to IPrintable, this should fail. printable = self.adaptation_manager.adapt( file_type, ex.IUndoable, None ) self.assertIsNone(printable) return def test_adaptation_prefers_subclasses(self): ex = self.examples # TextEditor->IPrintable. self.adaptation_manager.register_factory( factory=ex.TextEditorToIPrintable, from_protocol=ex.TextEditor, to_protocol=ex.IPrintable, ) # Editor->IPrintable. self.adaptation_manager.register_factory( factory=ex.EditorToIPrintable, from_protocol=ex.Editor, to_protocol=ex.IPrintable, ) # Create a text editor. text_editor = ex.TextEditor() # Adapt to IPrintable: we should get the TextEditorToIPrintable # adapter, not the EditorToIPrintable one. printable = self.adaptation_manager.adapt(text_editor, ex.IPrintable) self.assertIsNotNone(printable) self.assertIs(type(printable), ex.TextEditorToIPrintable) return def test_adaptation_prefers_subclasses_other_registration_order(self): # This test is identical to `test_adaptation_prefers_subclasses` # with adapters registered in the opposite order. Both of them # should pass ex = self.examples # Editor->IPrintable. self.adaptation_manager.register_factory( factory=ex.EditorToIPrintable, from_protocol=ex.Editor, to_protocol=ex.IPrintable, ) # TextEditor->IPrintable. self.adaptation_manager.register_factory( factory=ex.TextEditorToIPrintable, from_protocol=ex.TextEditor, to_protocol=ex.IPrintable, ) # Create a text editor. text_editor = ex.TextEditor() # Adapt to IPrintable: we should get the TextEditorToIPrintable # adapter, not the EditorToIPrintable one. printable = self.adaptation_manager.adapt(text_editor, ex.IPrintable) self.assertIsNotNone(printable) self.assertIs(type(printable), ex.TextEditorToIPrintable) return def test_circular_adaptation(self): # Circles in the adaptation graph should not lead to infinite loops # when it is impossible to reach the target. class Foo(object): pass class Bar(object): pass # object->Foo self.adaptation_manager.register_factory( factory=lambda adaptee: Foo(), from_protocol=object, to_protocol=Foo, ) # Foo->object self.adaptation_manager.register_factory( factory=lambda adaptee: [], from_protocol=Foo, to_protocol=object ) # Create an object. obj = [] # Try to adapt to an unreachable target. bar = self.adaptation_manager.adapt(obj, Bar, None) self.assertIsNone(bar) return def test_default_argument_in_adapt(self): from traits.adaptation.adaptation_manager import AdaptationError # Without a default argument, a failed adaptation raises an error. with self.assertRaises(AdaptationError): self.adaptation_manager.adapt("string", int) # With a default argument, a failed adaptation returns the default. default = "default" result = self.adaptation_manager.adapt("string", int, default=default) self.assertIs(result, default) return def test_prefer_specific_interfaces(self): ex = self.examples # IIntermediate -> ITarget. self.adaptation_manager.register_factory( factory=ex.IIntermediateToITarget, from_protocol=ex.IIntermediate, to_protocol=ex.ITarget, ) # IHuman -> IIntermediate. self.adaptation_manager.register_factory( factory=ex.IHumanToIIntermediate, from_protocol=ex.IHuman, to_protocol=ex.IIntermediate, ) # IChild -> IIntermediate. self.adaptation_manager.register_factory( factory=ex.IChildToIIntermediate, from_protocol=ex.IChild, to_protocol=ex.IIntermediate, ) # IPrimate -> IIntermediate. self.adaptation_manager.register_factory( factory=ex.IPrimateToIIntermediate, from_protocol=ex.IPrimate, to_protocol=ex.IIntermediate, ) # Create a source. source = ex.Source() # Adapt to ITarget: we should get the adapter for the most specific # interface, i.e. IChildToITarget. target = self.adaptation_manager.adapt(source, ex.ITarget) self.assertIsNotNone(target) self.assertIs(type(target.adaptee), ex.IChildToIIntermediate) return def test_chaining_with_intermediate_mro_climbing(self): ex = self.examples # IStart -> ISpecific. self.adaptation_manager.register_factory( factory=ex.IStartToISpecific, from_protocol=ex.IStart, to_protocol=ex.ISpecific, ) # IGeneric -> IEnd. self.adaptation_manager.register_factory( factory=ex.IGenericToIEnd, from_protocol=ex.IGeneric, to_protocol=ex.IEnd, ) # Create a start. start = ex.Start() # Adapt to IEnd; this should succeed going from IStart to ISpecific, # climbing up the MRO to IGeneric, then crossing to IEnd. end = self.adaptation_manager.adapt(start, ex.IEnd) self.assertIsNotNone(end) self.assertIs(type(end), ex.IGenericToIEnd) return def test_conditional_recycling(self): # Test that an offer that has been considered but failed if considered # again at a later time, when it might succeed because of conditional # adaptation. # C -- A -fails- B # C -- D -- A -succeeds- B class A(object): def __init__(self, allow_adaptation): self.allow_adaptation = allow_adaptation class B(object): pass class C(object): pass class D(object): pass self.adaptation_manager.register_factory( factory=lambda adaptee: A(False), from_protocol=C, to_protocol=A ) self.adaptation_manager.register_factory( factory=lambda adaptee: A(True), from_protocol=D, to_protocol=A ) self.adaptation_manager.register_factory( factory=lambda adaptee: D(), from_protocol=C, to_protocol=D ) # Conditional adapter def a_to_b_adapter(adaptee): if adaptee.allow_adaptation: b = B() b.marker = True else: b = None return b self.adaptation_manager.register_factory( factory=a_to_b_adapter, from_protocol=A, to_protocol=B ) # Create a A c = C() # Adaptation to B should succeed through D b = self.adaptation_manager.adapt(c, B) self.assertIsNotNone(b) self.assertTrue(hasattr(b, "marker")) return def test_provides_protocol_for_interface_subclass(self): from traits.api import Interface class IA(Interface): pass class IB(IA): pass self.assertTrue(self.adaptation_manager.provides_protocol(IB, IA)) return def test_register_provides(self): from traits.api import Interface class IFoo(Interface): pass obj = {} self.assertEqual(None, self.adaptation_manager.adapt(obj, IFoo, None)) self.adaptation_manager.register_provides(dict, IFoo) self.assertEqual(obj, self.adaptation_manager.adapt(obj, IFoo)) return
class TestAdaptationManagerWithABC(unittest.TestCase): """ Test the adapter manager. """ #: Class attribute pointing at the module containing the example data examples = traits.adaptation.tests.abc_examples #### 'TestCase' protocol ################################################## def setUp(self): """ Prepares the test fixture before each test method is called. """ self.adaptation_manager = AdaptationManager() return def tearDown(self): """ Called immediately after each test method has been called. """ return #### Tests ################################################################ def test_no_adapter_required(self): ex = self.examples plug = ex.UKPlug() # Try to adapt it to its own concrete type. uk_plug = self.adaptation_manager.adapt(plug, ex.UKPlug) # The adaptation manager should simply return the same object. self.assert_(uk_plug is plug) # Try to adapt it to an ABC that is registered for its type. uk_plug = self.adaptation_manager.adapt(plug, ex.UKStandard) # The adaptation manager should simply return the same object. self.assert_(uk_plug is plug) return def test_no_adapter_available(self): ex = self.examples plug = ex.UKPlug() # Try to adapt it to a concrete type. eu_plug = self.adaptation_manager.adapt(plug, ex.EUPlug, None) # There should be no way to adapt a UKPlug to a EUPlug. self.assertEqual(eu_plug, None) # Try to adapt it to an ABC. eu_plug = self.adaptation_manager.adapt(plug, ex.EUStandard, None) # There should be no way to adapt a UKPlug to a EUPlug. self.assertEqual(eu_plug, None) return def test_one_step_adaptation(self): ex = self.examples # UKStandard->EUStandard. self.adaptation_manager.register_factory( factory=ex.UKStandardToEUStandard, from_protocol=ex.UKStandard, to_protocol=ex.EUStandard) plug = ex.UKPlug() # Adapt it to an ABC. eu_plug = self.adaptation_manager.adapt(plug, ex.EUStandard) self.assertIsNotNone(eu_plug) self.assertIsInstance(eu_plug, ex.UKStandardToEUStandard) # We shouldn't be able to adapt it to a *concrete* 'EUPlug' though. eu_plug = self.adaptation_manager.adapt(plug, ex.EUPlug, None) self.assertIsNone(eu_plug) return def test_adapter_chaining(self): ex = self.examples # UKStandard->EUStandard. self.adaptation_manager.register_factory( factory=ex.UKStandardToEUStandard, from_protocol=ex.UKStandard, to_protocol=ex.EUStandard) # EUStandard->JapanStandard. self.adaptation_manager.register_factory( factory=ex.EUStandardToJapanStandard, from_protocol=ex.EUStandard, to_protocol=ex.JapanStandard) # Create a UKPlug. uk_plug = ex.UKPlug() # Adapt it to a JapanStandard via the chain. japan_plug = self.adaptation_manager.adapt(uk_plug, ex.JapanStandard) self.assertIsNotNone(japan_plug) self.assertIsInstance(japan_plug, ex.EUStandardToJapanStandard) self.assert_(japan_plug.adaptee.adaptee is uk_plug) return def test_multiple_paths_unambiguous(self): ex = self.examples # UKStandard->EUStandard. self.adaptation_manager.register_factory( factory=ex.UKStandardToEUStandard, from_protocol=ex.UKStandard, to_protocol=ex.EUStandard) # EUStandard->JapanStandard. self.adaptation_manager.register_factory( factory=ex.EUStandardToJapanStandard, from_protocol=ex.EUStandard, to_protocol=ex.JapanStandard) # JapanStandard->IraqStandard. self.adaptation_manager.register_factory( factory=ex.JapanStandardToIraqStandard, from_protocol=ex.JapanStandard, to_protocol=ex.IraqStandard) # EUStandard->IraqStandard. self.adaptation_manager.register_factory( factory=ex.EUStandardToIraqStandard, from_protocol=ex.EUStandard, to_protocol=ex.IraqStandard) # Create a UKPlug. uk_plug = ex.UKPlug() # Adapt it to a IraqStandard via the chain. iraq_plug = self.adaptation_manager.adapt(uk_plug, ex.IraqStandard) self.assertIsNotNone(iraq_plug) self.assertIsInstance(iraq_plug, ex.EUStandardToIraqStandard) self.assert_(iraq_plug.adaptee.adaptee is uk_plug) return def test_multiple_paths_ambiguous(self): ex = self.examples # UKStandard->EUStandard. self.adaptation_manager.register_factory( factory=ex.UKStandardToEUStandard, from_protocol=ex.UKStandard, to_protocol=ex.EUStandard) # UKStandard->JapanStandard. self.adaptation_manager.register_factory( factory=ex.UKStandardToJapanStandard, from_protocol=ex.UKStandard, to_protocol=ex.JapanStandard) # JapanStandard->IraqStandard. self.adaptation_manager.register_factory( factory=ex.JapanStandardToIraqStandard, from_protocol=ex.JapanStandard, to_protocol=ex.IraqStandard) # EUStandard->IraqStandard. self.adaptation_manager.register_factory( factory=ex.EUStandardToIraqStandard, from_protocol=ex.EUStandard, to_protocol=ex.IraqStandard) # Create a UKPlug. uk_plug = ex.UKPlug() # Adapt it to a IraqStandard via the chain. iraq_plug = self.adaptation_manager.adapt(uk_plug, ex.IraqStandard) self.assertIsNotNone(iraq_plug) self.assertIn( type(iraq_plug), [ex.EUStandardToIraqStandard, ex.JapanStandardToIraqStandard]) self.assert_(iraq_plug.adaptee.adaptee is uk_plug) return def test_conditional_adaptation(self): ex = self.examples # TravelPlug->EUStandard. def travel_plug_to_eu_standard(adaptee): if adaptee.mode == 'Europe': return ex.TravelPlugToEUStandard(adaptee=adaptee) else: return None self.adaptation_manager.register_factory( factory=travel_plug_to_eu_standard, from_protocol=ex.TravelPlug, to_protocol=ex.EUStandard) # Create a TravelPlug. travel_plug = ex.TravelPlug(mode='Europe') # Adapt it to a EUStandard. eu_plug = self.adaptation_manager.adapt(travel_plug, ex.EUStandard) self.assertIsNotNone(eu_plug) self.assertIsInstance(eu_plug, ex.TravelPlugToEUStandard) # Create a TravelPlug. travel_plug = ex.TravelPlug(mode='Asia') # Adapt it to a EUStandard. eu_plug = self.adaptation_manager.adapt(travel_plug, ex.EUStandard, None) self.assertIsNone(eu_plug) return def test_spillover_adaptation_behavior(self): ex = self.examples # FileType->IEditor. self.adaptation_manager.register_factory(factory=ex.FileTypeToIEditor, from_protocol=ex.FileType, to_protocol=ex.IEditor) # Meanwhile, in a plugin far, far away ... # IScriptable->IPrintable. self.adaptation_manager.register_factory( factory=ex.IScriptableToIUndoable, from_protocol=ex.IScriptable, to_protocol=ex.IUndoable) # Create a file type. file_type = ex.FileType() # Try to adapt to IPrintable: since we did not define an adapter # chain that goes from FileType to IPrintable, this should fail. printable = self.adaptation_manager.adapt(file_type, ex.IUndoable, None) self.assertIsNone(printable) return def test_adaptation_prefers_subclasses(self): ex = self.examples # TextEditor->IPrintable. self.adaptation_manager.register_factory( factory=ex.TextEditorToIPrintable, from_protocol=ex.TextEditor, to_protocol=ex.IPrintable) # Editor->IPrintable. self.adaptation_manager.register_factory(factory=ex.EditorToIPrintable, from_protocol=ex.Editor, to_protocol=ex.IPrintable) # Create a text editor. text_editor = ex.TextEditor() # Adapt to IPrintable: we should get the TextEditorToIPrintable # adapter, not the EditorToIPrintable one. printable = self.adaptation_manager.adapt(text_editor, ex.IPrintable) self.assertIsNotNone(printable) self.assertIs(type(printable), ex.TextEditorToIPrintable) return def test_adaptation_prefers_subclasses_other_registration_order(self): # This test is identical to `test_adaptation_prefers_subclasses` # with adapters registered in the opposite order. Both of them # should pass ex = self.examples # Editor->IPrintable. self.adaptation_manager.register_factory(factory=ex.EditorToIPrintable, from_protocol=ex.Editor, to_protocol=ex.IPrintable) # TextEditor->IPrintable. self.adaptation_manager.register_factory( factory=ex.TextEditorToIPrintable, from_protocol=ex.TextEditor, to_protocol=ex.IPrintable) # Create a text editor. text_editor = ex.TextEditor() # Adapt to IPrintable: we should get the TextEditorToIPrintable # adapter, not the EditorToIPrintable one. printable = self.adaptation_manager.adapt(text_editor, ex.IPrintable) self.assertIsNotNone(printable) self.assertIs(type(printable), ex.TextEditorToIPrintable) return def test_circular_adaptation(self): # Circles in the adaptation graph should not lead to infinite loops # when it is impossible to reach the target. class Foo(object): pass class Bar(object): pass # object->Foo self.adaptation_manager.register_factory(factory=lambda adaptee: Foo(), from_protocol=object, to_protocol=Foo) # Foo->object self.adaptation_manager.register_factory(factory=lambda adaptee: [], from_protocol=Foo, to_protocol=object) # Create an object. obj = [] # Try to adapt to an unreachable target. bar = self.adaptation_manager.adapt(obj, Bar, None) self.assertIsNone(bar) return def test_default_argument_in_adapt(self): from traits.adaptation.adaptation_manager import AdaptationError # Without a default argument, a failed adaptation raises an error. with self.assertRaises(AdaptationError): self.adaptation_manager.adapt('string', int) # With a default argument, a failed adaptation returns the default. default = 'default' result = self.adaptation_manager.adapt('string', int, default=default) self.assertIs(result, default) return def test_prefer_specific_interfaces(self): ex = self.examples # IIntermediate -> ITarget. self.adaptation_manager.register_factory( factory=ex.IIntermediateToITarget, from_protocol=ex.IIntermediate, to_protocol=ex.ITarget) # IHuman -> IIntermediate. self.adaptation_manager.register_factory( factory=ex.IHumanToIIntermediate, from_protocol=ex.IHuman, to_protocol=ex.IIntermediate) # IChild -> IIntermediate. self.adaptation_manager.register_factory( factory=ex.IChildToIIntermediate, from_protocol=ex.IChild, to_protocol=ex.IIntermediate) # IPrimate -> IIntermediate. self.adaptation_manager.register_factory( factory=ex.IPrimateToIIntermediate, from_protocol=ex.IPrimate, to_protocol=ex.IIntermediate) # Create a source. source = ex.Source() # Adapt to ITarget: we should get the adapter for the most specific # interface, i.e. IChildToITarget. target = self.adaptation_manager.adapt(source, ex.ITarget) self.assertIsNotNone(target) self.assertIs(type(target.adaptee), ex.IChildToIIntermediate) return def test_chaining_with_intermediate_mro_climbing(self): ex = self.examples # IStart -> ISpecific. self.adaptation_manager.register_factory(factory=ex.IStartToISpecific, from_protocol=ex.IStart, to_protocol=ex.ISpecific) # IGeneric -> IEnd. self.adaptation_manager.register_factory(factory=ex.IGenericToIEnd, from_protocol=ex.IGeneric, to_protocol=ex.IEnd) # Create a start. start = ex.Start() # Adapt to IEnd; this should succeed going from IStart to ISpecific, # climbing up the MRO to IGeneric, then crossing to IEnd. end = self.adaptation_manager.adapt(start, ex.IEnd) self.assertIsNotNone(end) self.assertIs(type(end), ex.IGenericToIEnd) return def test_conditional_recycling(self): # Test that an offer that has been considered but failed if considered # again at a later time, when it might succeed because of conditional # adaptation. # C -- A -fails- B # C -- D -- A -succeeds- B class A(object): def __init__(self, allow_adaptation): self.allow_adaptation = allow_adaptation class B(object): pass class C(object): pass class D(object): pass self.adaptation_manager.register_factory( factory=lambda adaptee: A(False), from_protocol=C, to_protocol=A) self.adaptation_manager.register_factory( factory=lambda adaptee: A(True), from_protocol=D, to_protocol=A) self.adaptation_manager.register_factory(factory=lambda adaptee: D(), from_protocol=C, to_protocol=D) # Conditional adapter def a_to_b_adapter(adaptee): if adaptee.allow_adaptation: b = B() b.marker = True else: b = None return b self.adaptation_manager.register_factory(factory=a_to_b_adapter, from_protocol=A, to_protocol=B) # Create a A c = C() # Adaptation to B should succeed through D b = self.adaptation_manager.adapt(c, B) self.assertIsNotNone(b) self.assert_(hasattr(b, 'marker')) return def test_provides_protocol_for_interface_subclass(self): from traits.api import Interface class IA(Interface): pass class IB(IA): pass self.assert_(self.adaptation_manager.provides_protocol(IB, IA)) return def test_register_provides(self): from traits.api import Interface class IFoo(Interface): pass obj = {} self.assertEqual(None, self.adaptation_manager.adapt(obj, IFoo, None)) self.adaptation_manager.register_provides(dict, IFoo) self.assertEqual(obj, self.adaptation_manager.adapt(obj, IFoo)) return
class TestCachedAdapterFactory(unittest.TestCase): """ Test the cached adapter factory. """ examples = traits.adaptation.tests.interface_examples #### 'TestCase' protocol ################################################## def setUp(self): """ Prepares the test fixture before each test method is called. """ self.adaptation_manager = AdaptationManager() return def tearDown(self): """ Called immediately after each test method has been called. """ return #### Tests ################################################################# def test_cached_adapters(self): ex = self.examples factory = CachedAdapterFactory(factory=ex.EditorToIPrintable) self.adaptation_manager.register_factory(factory=factory, from_protocol=ex.Editor, to_protocol=ex.IPrintable) editor = ex.Editor() adapter_1 = self.adaptation_manager.adapt(editor, ex.IPrintable) self.assertIsNotNone(adapter_1) self.assertIs(type(adapter_1), ex.EditorToIPrintable) adapter_2 = self.adaptation_manager.adapt(editor, ex.IPrintable) self.assertIsNotNone(adapter_2) self.assertIs(type(adapter_2), ex.EditorToIPrintable) self.assertIs(adapter_1, adapter_2) return @unittest.skip("Cache cleaning is broken: see GitHub issue #169") def test_cached_adapters_should_be_cleaned_up(self): ex = self.examples factory = CachedAdapterFactory(factory=ex.EditorToIPrintable) self.adaptation_manager.register_factory(factory=factory, from_protocol=ex.Editor, to_protocol=ex.IPrintable) editor = ex.Editor() adapter_1 = self.adaptation_manager.adapt(editor, ex.IPrintable) self.assertIsNotNone(adapter_1) self.assertIs(type(adapter_1), ex.EditorToIPrintable) del adapter_1 del editor self.assertTrue(factory.is_empty) return def test_cached_adapters_with_lazy_loaded_factory(self): LAZY_EXAMPLES = 'traits.adaptation.tests.lazy_examples' if LAZY_EXAMPLES in sys.modules: del sys.modules[LAZY_EXAMPLES] factory = CachedAdapterFactory(factory=LAZY_EXAMPLES + '.IBarToIFoo') self.adaptation_manager.register_factory( factory=factory, from_protocol=LAZY_EXAMPLES + '.IBar', to_protocol=LAZY_EXAMPLES + '.IFoo', ) self.assertNotIn(LAZY_EXAMPLES, sys.modules) # The *actual* factory is loaded on-demand. bogus = factory.factory self.assertIn(LAZY_EXAMPLES, sys.modules) return @unittest.skip("Cache cleaning is broken: see GitHub issue #169") def test_cached_adapter_that_was_garbage_collected(self): ex = self.examples factory = CachedAdapterFactory(factory=ex.EditorToIPrintable) self.adaptation_manager.register_factory(factory=factory, from_protocol=ex.Editor, to_protocol=ex.IPrintable) editor = ex.Editor() adapter_1 = self.adaptation_manager.adapt(editor, ex.IPrintable) self.assertIs(type(adapter_1), ex.EditorToIPrintable) adapter_1.marker = 'marker' del adapter_1 adapter_2 = self.adaptation_manager.adapt(editor, ex.IPrintable) self.assertIsNotNone(adapter_2) self.assertTrue(hasattr(adapter_2, 'marker')) del adapter_2 del editor self.assertTrue(factory.is_empty)