def queryMultiAdapter(self, objects, interface, name='', default=None):
factory = self.lookup(map(providedBy, objects), interface, name)
if factory is not None:
return factory(*objects)
return default
これだけではたいしたことはわからない。なんか検索して戻って来るのはfactoryで、そいつにinterfaceを満たすobjectのインスタンスを生成させている。なのでlookupの実装と、lookupの実装で探しているコンテナを特定し、InterfaceをregisterするAPIを読み解かないといけない。
class AdapterLookup(object):
# Adapter lookup support
# We have a class here because we want to provide very
# fast lookup support in C and making this part of the adapter
# registry itself would provide problems if someone wanted to
# persistent adapter registries, because we want C slots for fast
# lookup that would clash with persistence-suppplied slots.
# so this class acts a little bit like a lookup adapter for the adapter
# registry.
def __init__(self, registry, surrogates, _remove):
self._registry = registry
self._surrogateClass = registry._surrogateClass
self._default = registry._default
self._null = registry._null
self._surrogates = surrogates
self._remove = _remove
問題のlookup.
def lookup(self, required, provided, name='', default=None):
order = len(required)
if order == 1:
# Simple adapter:
s = self.get(required[0])
byname = s.get(provided)
if byname:
value = byname.get(name)
else:
value = None
if value is None:
byname = self._default.get(provided)
if byname:
value = byname.get(name, default)
else:
return default
return value
orderが0ってことはrequieredは[]とか()だ。どういう状況なのだろうか?
elif order == 0:
# null adapter
byname = self._null.get(provided)
if byname:
return byname.get(name, default)
else:
return default
getが取り出す操作を担当。ここにあるのはどれがbest matchかを決める実装
# Multi adapter
with = required[1:]
key = provided, order
for surrogate in self.get(required[0]), self._default:
byname = surrogate.get(key)
if not byname:
continue
bywith = byname.get(name)
if not bywith:
continue
# Selecting multi-adapters is not just a matter of matching the
# required interfaces of the adapter to the ones passed. Several
# adapters might match, but we only want the best one. We use a
# ranking algorithm to determine the best match.
# `best` carries the rank and value of the best found adapter.
best = None
for rwith, value in bywith:
# the `rank` describes how well the found adapter matches.
rank = []
for rspec, spec in zip(rwith, with):
if not spec.isOrExtends(rspec):
break # This one is no good
# Determine the rank of this particular specification.
rank.append(list(spec.__sro__).index(rspec))
else:
# If the new rank is better than the best previously
# recorded one, make the new adapter the best one found.
rank = tuple(rank)
if best is None or rank < best[0]:
best = rank, value
# If any match was found, return the best one.
if best:
return best[1]
return default
method weakrefはweakrefだろう。なぜ使っているのか理解するべし。
なぜsurrogateなのか
def get(self, declaration):
if declaration is None:
return self._default
ref = declaration.weakref(self._remove)
surrogate = self._surrogates.get(ref)
if surrogate is None:
surrogate = self._surrogateClass(declaration, self._registry)
self._surrogates[ref] = surrogate
return surrogate
0 件のコメント:
コメントを投稿