2009年3月2日月曜日

zope:queryMultiAdapater

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
おそらく/usr/lib64/python/site-packages/zope/interface/adapter.pyのこれなんだろう。



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 件のコメント: