ProtocolSubsets |
UserPreferences |
The PEAK Developers' Center | FrontPage | RecentChanges | TitleIndex | WordIndex | SiteNavigation | HelpContents |
I originally posted this here but figured it would be good netiquette to re-post the details of it on this wiki :-) Comments/corrections greatly appreciated.
If you have code similar to the following, which produces a "?TypeError" with an "Ambiguous adapter choice" error message, you are probably making an incorrect assumption about how to differentiate interfaces that are related to eachother via another interface that is common between them. ("Fixed" code is below the "Broken" code)
1 #!/usr/bin/env python 2 3 import protocols 4 5 class IBase(protocols.Interface): 6 pass 7 class IWhy(IBase): 8 pass 9 class IZee(IBase): 10 pass 11 12 class X(object): 13 value = 'foo' 14 class Y(object): 15 protocols.advise(instancesProvide=[IWhy]) 16 def __init__(self, ob): 17 self.value = ob.value + 'bar' 18 class Z(object): 19 protocols.advise(instancesProvide=[IZee]) 20 def __init__(self, ob): 21 self.value = ob.value + 'baz' 22 23 protocols.declareAdapter(factory=Y, provides=[IWhy], forTypes=[X]) 24 protocols.declareAdapter(factory=Z, provides=[IZee], forTypes=[X]) 25 26 x = X(); print 'x', x.value 27 y = IWhy(x); print 'y', y.value 28 z = IZee(x); print 'z', z.value
Subclassing IBase as shown above *extends* it which make IWhy and IZee ambiguously similar since they both have the entire IBase interface in common. Instead, to differentiate them you want to make IWhy and IZee *subsets* of IBase:
1 #!/usr/bin/env python 2 3 import protocols 4 5 class IBase(protocols.Interface): 6 pass 7 class IWhy(protocols.Interface): 8 protocols.advise(protocolIsSubsetOf=[IBase]) 9 class IZee(protocols.Interface): 10 protocols.advise(protocolIsSubsetOf=[IBase]) 11 12 class X(object): 13 value = 'foo' 14 class Y(object): 15 protocols.advise(instancesProvide=[IWhy]) 16 def __init__(self, ob): 17 self.value = ob.value + 'bar' 18 class Z(object): 19 protocols.advise(instancesProvide=[IZee]) 20 def __init__(self, ob): 21 self.value = ob.value + 'baz' 22 23 protocols.declareAdapter(factory=Y, provides=[IWhy], forTypes=[X]) 24 protocols.declareAdapter(factory=Z, provides=[IZee], forTypes=[X]) 25 26 x = X(); print 'x', x.value 27 y = IWhy(x); print 'y', y.value 28 z = IZee(x); print 'z', z.value