test_adapter.py 79 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315
  1. ##############################################################################
  2. #
  3. # Copyright (c) 2003 Zope Foundation and Contributors.
  4. # All Rights Reserved.
  5. #
  6. # This software is subject to the provisions of the Zope Public License,
  7. # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
  8. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
  9. # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  10. # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
  11. # FOR A PARTICULAR PURPOSE.
  12. #
  13. ##############################################################################
  14. """Adapter registry tests
  15. """
  16. import unittest
  17. from __tests__.tests import OptimizationTestMixin
  18. # pylint:disable=inherit-non-class,protected-access,too-many-lines
  19. # pylint:disable=attribute-defined-outside-init,blacklisted-name
  20. def _makeInterfaces():
  21. from zope.interface import Interface
  22. class IB0(Interface):
  23. pass
  24. class IB1(IB0):
  25. pass
  26. class IB2(IB0):
  27. pass
  28. class IB3(IB2, IB1):
  29. pass
  30. class IB4(IB1, IB2):
  31. pass
  32. class IF0(Interface):
  33. pass
  34. class IF1(IF0):
  35. pass
  36. class IR0(Interface):
  37. pass
  38. class IR1(IR0):
  39. pass
  40. return IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1
  41. # Custom types to use as part of the AdapterRegistry data structures.
  42. # Our custom types do strict type checking to make sure
  43. # types propagate through the data tree as expected.
  44. class CustomDataTypeBase:
  45. _data = None
  46. def __getitem__(self, name):
  47. return self._data[name]
  48. def __setitem__(self, name, value):
  49. self._data[name] = value
  50. def __delitem__(self, name):
  51. del self._data[name]
  52. def __len__(self):
  53. return len(self._data)
  54. def __contains__(self, name):
  55. return name in self._data
  56. def __eq__(self, other):
  57. if other is self:
  58. return True
  59. # pylint:disable=unidiomatic-typecheck
  60. if type(other) is not type(self):
  61. return False
  62. return other._data == self._data
  63. def __repr__(self):
  64. return repr(self._data)
  65. class CustomMapping(CustomDataTypeBase):
  66. def __init__(self, other=None):
  67. self._data = {}
  68. if other:
  69. self._data.update(other)
  70. self.get = self._data.get
  71. self.items = self._data.items
  72. class CustomSequence(CustomDataTypeBase):
  73. def __init__(self, other=None):
  74. self._data = []
  75. if other:
  76. self._data.extend(other)
  77. self.append = self._data.append
  78. class CustomLeafSequence(CustomSequence):
  79. pass
  80. class CustomProvided(CustomMapping):
  81. pass
  82. class BaseAdapterRegistryTests(unittest.TestCase):
  83. maxDiff = None
  84. def _getBaseAdapterRegistry(self):
  85. from zope.interface.adapter import BaseAdapterRegistry
  86. return BaseAdapterRegistry
  87. def _getTargetClass(self):
  88. BaseAdapterRegistry = self._getBaseAdapterRegistry()
  89. class _CUT(BaseAdapterRegistry):
  90. class LookupClass:
  91. _changed = _extendors = ()
  92. def __init__(self, reg):
  93. pass
  94. def changed(self, orig):
  95. self._changed += (orig,)
  96. def add_extendor(self, provided):
  97. self._extendors += (provided,)
  98. def remove_extendor(self, provided):
  99. self._extendors = tuple([x for x in self._extendors
  100. if x != provided])
  101. for name in BaseAdapterRegistry._delegated:
  102. setattr(_CUT.LookupClass, name, object())
  103. return _CUT
  104. def _makeOne(self):
  105. return self._getTargetClass()()
  106. def _getMappingType(self):
  107. return dict
  108. def _getProvidedType(self):
  109. return dict
  110. def _getMutableListType(self):
  111. return list
  112. def _getLeafSequenceType(self):
  113. return tuple
  114. def test_lookup_delegation(self):
  115. CUT = self._getTargetClass()
  116. registry = CUT()
  117. for name in CUT._delegated:
  118. self.assertIs(
  119. getattr(registry, name), getattr(registry._v_lookup, name)
  120. )
  121. def test__generation_on_first_creation(self):
  122. registry = self._makeOne()
  123. # Bumped to 1 in BaseAdapterRegistry.__init__
  124. self.assertEqual(registry._generation, 1)
  125. def test__generation_after_calling_changed(self):
  126. registry = self._makeOne()
  127. orig = object()
  128. registry.changed(orig)
  129. # Bumped to 1 in BaseAdapterRegistry.__init__
  130. self.assertEqual(registry._generation, 2)
  131. self.assertEqual(registry._v_lookup._changed, (registry, orig,))
  132. def test__generation_after_changing___bases__(self):
  133. class _Base:
  134. pass
  135. registry = self._makeOne()
  136. registry.__bases__ = (_Base,)
  137. self.assertEqual(registry._generation, 2)
  138. def _check_basic_types_of_adapters(self, registry, expected_order=2):
  139. self.assertEqual(
  140. len(registry._adapters), expected_order,
  141. ) # order 0 and order 1
  142. self.assertIsInstance(registry._adapters, self._getMutableListType())
  143. MT = self._getMappingType()
  144. for mapping in registry._adapters:
  145. self.assertIsInstance(mapping, MT)
  146. self.assertEqual(registry._adapters[0], MT())
  147. self.assertIsInstance(registry._adapters[1], MT)
  148. self.assertEqual(len(registry._adapters[expected_order - 1]), 1)
  149. def _check_basic_types_of_subscribers(self, registry, expected_order=2):
  150. self.assertEqual(
  151. len(registry._subscribers), expected_order,
  152. ) # order 0 and order 1
  153. self.assertIsInstance(
  154. registry._subscribers, self._getMutableListType(),
  155. )
  156. MT = self._getMappingType()
  157. for mapping in registry._subscribers:
  158. self.assertIsInstance(mapping, MT)
  159. if expected_order:
  160. self.assertEqual(registry._subscribers[0], MT())
  161. self.assertIsInstance(registry._subscribers[1], MT)
  162. self.assertEqual(len(registry._subscribers[expected_order - 1]), 1)
  163. def test_register(self):
  164. (
  165. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  166. ) = _makeInterfaces() # pylint:disable=unused-variable
  167. registry = self._makeOne()
  168. registry.register([IB0], IR0, '', 'A1')
  169. self.assertEqual(registry.registered([IB0], IR0, ''), 'A1')
  170. self.assertEqual(registry._generation, 2)
  171. self._check_basic_types_of_adapters(registry)
  172. MT = self._getMappingType()
  173. self.assertEqual(registry._adapters[1], MT({
  174. IB0: MT({
  175. IR0: MT({'': 'A1'})
  176. })
  177. }))
  178. PT = self._getProvidedType()
  179. self.assertEqual(registry._provided, PT({
  180. IR0: 1
  181. }))
  182. registered = list(registry.allRegistrations())
  183. self.assertEqual(registered, [(
  184. (IB0,), # required
  185. IR0, # provided
  186. '', # name
  187. 'A1' # value
  188. )])
  189. def test_register_multiple_allRegistrations(self):
  190. (
  191. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  192. ) = _makeInterfaces() # pylint:disable=unused-variable
  193. registry = self._makeOne()
  194. # Use several different depths and several different names
  195. registry.register([], IR0, '', 'A1')
  196. registry.register([], IR0, 'name1', 'A2')
  197. registry.register([IB0], IR0, '', 'A1')
  198. registry.register([IB0], IR0, 'name2', 'A2')
  199. registry.register([IB0], IR1, '', 'A3')
  200. registry.register([IB0], IR1, 'name3', 'A4')
  201. registry.register([IB0, IB1], IR0, '', 'A1')
  202. registry.register([IB0, IB2], IR0, 'name2', 'A2')
  203. registry.register([IB0, IB2], IR1, 'name4', 'A4')
  204. registry.register([IB0, IB3], IR1, '', 'A3')
  205. def build_adapters(L, MT):
  206. return L([
  207. # 0
  208. MT({
  209. IR0: MT({
  210. '': 'A1',
  211. 'name1': 'A2'
  212. })
  213. }),
  214. # 1
  215. MT({
  216. IB0: MT({
  217. IR0: MT({
  218. '': 'A1',
  219. 'name2': 'A2'
  220. }),
  221. IR1: MT({
  222. '': 'A3',
  223. 'name3': 'A4'
  224. })
  225. })
  226. }),
  227. # 3
  228. MT({
  229. IB0: MT({
  230. IB1: MT({
  231. IR0: MT({'': 'A1'})
  232. }),
  233. IB2: MT({
  234. IR0: MT({'name2': 'A2'}),
  235. IR1: MT({'name4': 'A4'}),
  236. }),
  237. IB3: MT({
  238. IR1: MT({'': 'A3'})
  239. })
  240. }),
  241. }),
  242. ])
  243. self.assertEqual(registry._adapters,
  244. build_adapters(L=self._getMutableListType(),
  245. MT=self._getMappingType()))
  246. registered = sorted(registry.allRegistrations())
  247. self.assertEqual(registered, [
  248. ((), IR0, '', 'A1'),
  249. ((), IR0, 'name1', 'A2'),
  250. ((IB0,), IR0, '', 'A1'),
  251. ((IB0,), IR0, 'name2', 'A2'),
  252. ((IB0,), IR1, '', 'A3'),
  253. ((IB0,), IR1, 'name3', 'A4'),
  254. ((IB0, IB1), IR0, '', 'A1'),
  255. ((IB0, IB2), IR0, 'name2', 'A2'),
  256. ((IB0, IB2), IR1, 'name4', 'A4'),
  257. ((IB0, IB3), IR1, '', 'A3')
  258. ])
  259. # We can duplicate to another object.
  260. registry2 = self._makeOne()
  261. for args in registered:
  262. registry2.register(*args)
  263. self.assertEqual(registry2._adapters, registry._adapters)
  264. self.assertEqual(registry2._provided, registry._provided)
  265. # We can change the types and rebuild the data structures.
  266. registry._mappingType = CustomMapping
  267. registry._leafSequenceType = CustomLeafSequence
  268. registry._sequenceType = CustomSequence
  269. registry._providedType = CustomProvided
  270. def addValue(existing, new):
  271. existing = (
  272. existing if existing is not None else CustomLeafSequence()
  273. )
  274. existing.append(new)
  275. return existing
  276. registry._addValueToLeaf = addValue
  277. registry.rebuild()
  278. self.assertEqual(registry._adapters,
  279. build_adapters(
  280. L=CustomSequence,
  281. MT=CustomMapping
  282. ))
  283. def test_register_with_invalid_name(self):
  284. (
  285. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  286. ) = _makeInterfaces() # pylint:disable=unused-variable
  287. registry = self._makeOne()
  288. with self.assertRaises(ValueError):
  289. registry.register([IB0], IR0, object(), 'A1')
  290. def test_register_with_value_None_unregisters(self):
  291. (
  292. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  293. ) = _makeInterfaces() # pylint:disable=unused-variable
  294. registry = self._makeOne()
  295. registry.register([None], IR0, '', 'A1')
  296. registry.register([None], IR0, '', None)
  297. self.assertEqual(len(registry._adapters), 0)
  298. self.assertIsInstance(registry._adapters, self._getMutableListType())
  299. registered = list(registry.allRegistrations())
  300. self.assertEqual(registered, [])
  301. def test_register_with_same_value(self):
  302. from zope.interface import Interface
  303. (
  304. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  305. ) = _makeInterfaces() # pylint:disable=unused-variable
  306. registry = self._makeOne()
  307. _value = object()
  308. registry.register([None], IR0, '', _value)
  309. _before = registry._generation
  310. registry.register([None], IR0, '', _value)
  311. self.assertEqual(registry._generation, _before) # skipped changed()
  312. self._check_basic_types_of_adapters(registry)
  313. MT = self._getMappingType()
  314. self.assertEqual(registry._adapters[1], MT(
  315. {
  316. Interface: MT(
  317. {
  318. IR0: MT({'': _value})
  319. }
  320. )
  321. }
  322. ))
  323. registered = list(registry.allRegistrations())
  324. self.assertEqual(registered, [(
  325. (Interface,), # required
  326. IR0, # provided
  327. '', # name
  328. _value # value
  329. )])
  330. def test_registered_empty(self):
  331. registry = self._makeOne()
  332. self.assertEqual(registry.registered([None], None, ''), None)
  333. registered = list(registry.allRegistrations())
  334. self.assertEqual(registered, [])
  335. def test_registered_non_empty_miss(self):
  336. (
  337. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  338. ) = _makeInterfaces() # pylint:disable=unused-variable
  339. registry = self._makeOne()
  340. registry.register([IB1], None, '', 'A1')
  341. self.assertEqual(registry.registered([IB2], None, ''), None)
  342. def test_registered_non_empty_hit(self):
  343. registry = self._makeOne()
  344. registry.register([None], None, '', 'A1')
  345. self.assertEqual(registry.registered([None], None, ''), 'A1')
  346. def test_unregister_empty(self):
  347. registry = self._makeOne()
  348. registry.unregister([None], None, '') # doesn't raise
  349. self.assertEqual(registry.registered([None], None, ''), None)
  350. self.assertEqual(len(registry._provided), 0)
  351. def test_unregister_non_empty_miss_on_required(self):
  352. (
  353. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  354. ) = _makeInterfaces() # pylint:disable=unused-variable
  355. registry = self._makeOne()
  356. registry.register([IB1], None, '', 'A1')
  357. registry.unregister([IB2], None, '') # doesn't raise
  358. self.assertEqual(registry.registered([IB1], None, ''), 'A1')
  359. self._check_basic_types_of_adapters(registry)
  360. MT = self._getMappingType()
  361. self.assertEqual(registry._adapters[1], MT(
  362. {
  363. IB1: MT(
  364. {
  365. None: MT({'': 'A1'})
  366. }
  367. )
  368. }
  369. ))
  370. PT = self._getProvidedType()
  371. self.assertEqual(registry._provided, PT({
  372. None: 1
  373. }))
  374. def test_unregister_non_empty_miss_on_name(self):
  375. (
  376. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  377. ) = _makeInterfaces() # pylint:disable=unused-variable
  378. registry = self._makeOne()
  379. registry.register([IB1], None, '', 'A1')
  380. registry.unregister([IB1], None, 'nonesuch') # doesn't raise
  381. self.assertEqual(registry.registered([IB1], None, ''), 'A1')
  382. self._check_basic_types_of_adapters(registry)
  383. MT = self._getMappingType()
  384. self.assertEqual(registry._adapters[1], MT(
  385. {
  386. IB1: MT(
  387. {
  388. None: MT({'': 'A1'})
  389. }
  390. )
  391. }
  392. ))
  393. PT = self._getProvidedType()
  394. self.assertEqual(registry._provided, PT({
  395. None: 1
  396. }))
  397. def test_unregister_with_value_not_None_miss(self):
  398. (
  399. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  400. ) = _makeInterfaces() # pylint:disable=unused-variable
  401. registry = self._makeOne()
  402. orig = object()
  403. nomatch = object()
  404. registry.register([IB1], None, '', orig)
  405. registry.unregister([IB1], None, '', nomatch) # doesn't raise
  406. self.assertIs(registry.registered([IB1], None, ''), orig)
  407. def test_unregister_hit_clears_empty_subcomponents(self):
  408. (
  409. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  410. ) = _makeInterfaces() # pylint:disable=unused-variable
  411. registry = self._makeOne()
  412. one = object()
  413. another = object()
  414. registry.register([IB1, IB2], None, '', one)
  415. registry.register([IB1, IB3], None, '', another)
  416. self._check_basic_types_of_adapters(registry, expected_order=3)
  417. self.assertIn(IB2, registry._adapters[2][IB1])
  418. self.assertIn(IB3, registry._adapters[2][IB1])
  419. MT = self._getMappingType()
  420. self.assertEqual(registry._adapters[2], MT(
  421. {
  422. IB1: MT(
  423. {
  424. IB2: MT({None: MT({'': one})}),
  425. IB3: MT({None: MT({'': another})})
  426. }
  427. )
  428. }
  429. ))
  430. PT = self._getProvidedType()
  431. self.assertEqual(registry._provided, PT({
  432. None: 2
  433. }))
  434. registry.unregister([IB1, IB3], None, '', another)
  435. self.assertIn(IB2, registry._adapters[2][IB1])
  436. self.assertNotIn(IB3, registry._adapters[2][IB1])
  437. self.assertEqual(registry._adapters[2], MT(
  438. {
  439. IB1: MT(
  440. {
  441. IB2: MT({None: MT({'': one})}),
  442. }
  443. )
  444. }
  445. ))
  446. self.assertEqual(registry._provided, PT({
  447. None: 1
  448. }))
  449. def test_unsubscribe_empty(self):
  450. registry = self._makeOne()
  451. registry.unsubscribe([None], None, '') # doesn't raise
  452. self.assertEqual(registry.registered([None], None, ''), None)
  453. self._check_basic_types_of_subscribers(registry, expected_order=0)
  454. def test_unsubscribe_hit(self):
  455. (
  456. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  457. ) = _makeInterfaces() # pylint:disable=unused-variable
  458. registry = self._makeOne()
  459. orig = object()
  460. registry.subscribe([IB1], None, orig)
  461. MT = self._getMappingType()
  462. L = self._getLeafSequenceType()
  463. PT = self._getProvidedType()
  464. self._check_basic_types_of_subscribers(registry)
  465. self.assertEqual(registry._subscribers[1], MT({
  466. IB1: MT({
  467. None: MT({
  468. '': L((orig,))
  469. })
  470. })
  471. }))
  472. self.assertEqual(registry._provided, PT({}))
  473. registry.unsubscribe([IB1], None, orig) # doesn't raise
  474. self.assertEqual(len(registry._subscribers), 0)
  475. self.assertEqual(registry._provided, PT({}))
  476. def assertLeafIdentity(self, leaf1, leaf2):
  477. """
  478. Implementations may choose to use new, immutable objects
  479. instead of mutating existing subscriber leaf objects, or vice versa.
  480. The default implementation uses immutable tuples, so they are never
  481. the same. Other implementations may use persistent lists so they
  482. should be the same and mutated in place. Subclasses testing this
  483. behaviour need to override this method.
  484. """
  485. self.assertIsNot(leaf1, leaf2)
  486. def test_unsubscribe_after_multiple(self):
  487. (
  488. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  489. ) = _makeInterfaces() # pylint:disable=unused-variable
  490. registry = self._makeOne()
  491. first = object()
  492. second = object()
  493. third = object()
  494. fourth = object()
  495. registry.subscribe([IB1], None, first)
  496. registry.subscribe([IB1], None, second)
  497. registry.subscribe([IB1], IR0, third)
  498. registry.subscribe([IB1], IR0, fourth)
  499. self._check_basic_types_of_subscribers(registry, expected_order=2)
  500. MT = self._getMappingType()
  501. L = self._getLeafSequenceType()
  502. PT = self._getProvidedType()
  503. self.assertEqual(registry._subscribers[1], MT({
  504. IB1: MT({
  505. None: MT({'': L((first, second))}),
  506. IR0: MT({'': L((third, fourth))}),
  507. })
  508. }))
  509. self.assertEqual(registry._provided, PT({
  510. IR0: 2
  511. }))
  512. # The leaf objects may or may not stay the same as they are
  513. # unsubscribed, depending on the implementation
  514. IR0_leaf_orig = registry._subscribers[1][IB1][IR0]['']
  515. Non_leaf_orig = registry._subscribers[1][IB1][None]['']
  516. registry.unsubscribe([IB1], None, first)
  517. registry.unsubscribe([IB1], IR0, third)
  518. self.assertEqual(registry._subscribers[1], MT({
  519. IB1: MT({
  520. None: MT({'': L((second,))}),
  521. IR0: MT({'': L((fourth,))}),
  522. })
  523. }))
  524. self.assertEqual(registry._provided, PT({
  525. IR0: 1
  526. }))
  527. IR0_leaf_new = registry._subscribers[1][IB1][IR0]['']
  528. Non_leaf_new = registry._subscribers[1][IB1][None]['']
  529. self.assertLeafIdentity(IR0_leaf_orig, IR0_leaf_new)
  530. self.assertLeafIdentity(Non_leaf_orig, Non_leaf_new)
  531. registry.unsubscribe([IB1], None, second)
  532. registry.unsubscribe([IB1], IR0, fourth)
  533. self.assertEqual(len(registry._subscribers), 0)
  534. self.assertEqual(len(registry._provided), 0)
  535. def test_subscribe_unsubscribe_identical_objects_provided(self):
  536. # https://github.com/zopefoundation/zope.interface/issues/227
  537. (
  538. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  539. ) = _makeInterfaces() # pylint:disable=unused-variable
  540. registry = self._makeOne()
  541. first = object()
  542. registry.subscribe([IB1], IR0, first)
  543. registry.subscribe([IB1], IR0, first)
  544. MT = self._getMappingType()
  545. L = self._getLeafSequenceType()
  546. PT = self._getProvidedType()
  547. self.assertEqual(registry._subscribers[1], MT({
  548. IB1: MT({
  549. IR0: MT({'': L((first, first))}),
  550. })
  551. }))
  552. self.assertEqual(registry._provided, PT({
  553. IR0: 2
  554. }))
  555. registry.unsubscribe([IB1], IR0, first)
  556. registry.unsubscribe([IB1], IR0, first)
  557. self.assertEqual(len(registry._subscribers), 0)
  558. self.assertEqual(registry._provided, PT())
  559. def test_subscribe_unsubscribe_nonequal_objects_provided(self):
  560. # https://github.com/zopefoundation/zope.interface/issues/227
  561. (
  562. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  563. ) = _makeInterfaces() # pylint:disable=unused-variable
  564. registry = self._makeOne()
  565. first = object()
  566. second = object()
  567. registry.subscribe([IB1], IR0, first)
  568. registry.subscribe([IB1], IR0, second)
  569. MT = self._getMappingType()
  570. L = self._getLeafSequenceType()
  571. PT = self._getProvidedType()
  572. self.assertEqual(registry._subscribers[1], MT({
  573. IB1: MT({
  574. IR0: MT({'': L((first, second))}),
  575. })
  576. }))
  577. self.assertEqual(registry._provided, PT({
  578. IR0: 2
  579. }))
  580. registry.unsubscribe([IB1], IR0, first)
  581. registry.unsubscribe([IB1], IR0, second)
  582. self.assertEqual(len(registry._subscribers), 0)
  583. self.assertEqual(registry._provided, PT())
  584. def test_subscribed_empty(self):
  585. registry = self._makeOne()
  586. self.assertIsNone(registry.subscribed([None], None, ''))
  587. subscribed = list(registry.allSubscriptions())
  588. self.assertEqual(subscribed, [])
  589. def test_subscribed_non_empty_miss(self):
  590. (
  591. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  592. ) = _makeInterfaces() # pylint:disable=unused-variable
  593. registry = self._makeOne()
  594. registry.subscribe([IB1], IF0, 'A1')
  595. # Mismatch required
  596. self.assertIsNone(registry.subscribed([IB2], IF0, ''))
  597. # Mismatch provided
  598. self.assertIsNone(registry.subscribed([IB1], IF1, ''))
  599. # Mismatch value
  600. self.assertIsNone(registry.subscribed([IB1], IF0, ''))
  601. def test_subscribed_non_empty_hit(self):
  602. (
  603. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  604. ) = _makeInterfaces() # pylint:disable=unused-variable
  605. registry = self._makeOne()
  606. registry.subscribe([IB0], IF0, 'A1')
  607. self.assertEqual(registry.subscribed([IB0], IF0, 'A1'), 'A1')
  608. def test_unsubscribe_w_None_after_multiple(self):
  609. (
  610. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  611. ) = _makeInterfaces() # pylint:disable=unused-variable
  612. registry = self._makeOne()
  613. first = object()
  614. second = object()
  615. registry.subscribe([IB1], None, first)
  616. registry.subscribe([IB1], None, second)
  617. self._check_basic_types_of_subscribers(registry, expected_order=2)
  618. registry.unsubscribe([IB1], None)
  619. self.assertEqual(len(registry._subscribers), 0)
  620. def test_unsubscribe_non_empty_miss_on_required(self):
  621. (
  622. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  623. ) = _makeInterfaces() # pylint:disable=unused-variable
  624. registry = self._makeOne()
  625. registry.subscribe([IB1], None, 'A1')
  626. self._check_basic_types_of_subscribers(registry, expected_order=2)
  627. registry.unsubscribe([IB2], None, '') # doesn't raise
  628. self.assertEqual(len(registry._subscribers), 2)
  629. MT = self._getMappingType()
  630. L = self._getLeafSequenceType()
  631. self.assertEqual(registry._subscribers[1], MT({
  632. IB1: MT({
  633. None: MT({'': L(('A1',))}),
  634. })
  635. }))
  636. def test_unsubscribe_non_empty_miss_on_value(self):
  637. (
  638. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  639. ) = _makeInterfaces() # pylint:disable=unused-variable
  640. registry = self._makeOne()
  641. registry.subscribe([IB1], None, 'A1')
  642. self._check_basic_types_of_subscribers(registry, expected_order=2)
  643. registry.unsubscribe([IB1], None, 'A2') # doesn't raise
  644. self.assertEqual(len(registry._subscribers), 2)
  645. MT = self._getMappingType()
  646. L = self._getLeafSequenceType()
  647. self.assertEqual(registry._subscribers[1], MT({
  648. IB1: MT({
  649. None: MT({'': L(('A1',))}),
  650. })
  651. }))
  652. def test_unsubscribe_with_value_not_None_miss(self):
  653. (
  654. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  655. ) = _makeInterfaces() # pylint:disable=unused-variable
  656. registry = self._makeOne()
  657. orig = object()
  658. nomatch = object()
  659. registry.subscribe([IB1], None, orig)
  660. registry.unsubscribe([IB1], None, nomatch) # doesn't raise
  661. self.assertEqual(len(registry._subscribers), 2)
  662. def _instance_method_notify_target(self):
  663. self.fail("Example method, not intended to be called.")
  664. def test_unsubscribe_instance_method(self):
  665. # Checking that the values are compared by equality, not identity
  666. (
  667. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  668. ) = _makeInterfaces() # pylint:disable=unused-variable
  669. registry = self._makeOne()
  670. self.assertEqual(len(registry._subscribers), 0)
  671. registry.subscribe([IB1], None, self._instance_method_notify_target)
  672. registry.unsubscribe([IB1], None, self._instance_method_notify_target)
  673. self.assertEqual(len(registry._subscribers), 0)
  674. def test_subscribe_multiple_allRegistrations(self):
  675. (
  676. IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1,
  677. ) = _makeInterfaces() # pylint:disable=unused-variable
  678. registry = self._makeOne()
  679. # Use several different depths and several different values
  680. registry.subscribe([], IR0, 'A1')
  681. registry.subscribe([], IR0, 'A2')
  682. registry.subscribe([IB0], IR0, 'A1')
  683. registry.subscribe([IB0], IR0, 'A2')
  684. registry.subscribe([IB0], IR1, 'A3')
  685. registry.subscribe([IB0], IR1, 'A4')
  686. registry.subscribe([IB0, IB1], IR0, 'A1')
  687. registry.subscribe([IB0, IB2], IR0, 'A2')
  688. registry.subscribe([IB0, IB2], IR1, 'A4')
  689. registry.subscribe([IB0, IB3], IR1, 'A3')
  690. def build_subscribers(L, F, MT):
  691. return L([
  692. # 0
  693. MT({
  694. IR0: MT({
  695. '': F(['A1', 'A2'])
  696. })
  697. }),
  698. # 1
  699. MT({
  700. IB0: MT({
  701. IR0: MT({
  702. '': F(['A1', 'A2'])
  703. }),
  704. IR1: MT({
  705. '': F(['A3', 'A4'])
  706. })
  707. })
  708. }),
  709. # 3
  710. MT({
  711. IB0: MT({
  712. IB1: MT({
  713. IR0: MT({'': F(['A1'])})
  714. }),
  715. IB2: MT({
  716. IR0: MT({'': F(['A2'])}),
  717. IR1: MT({'': F(['A4'])}),
  718. }),
  719. IB3: MT({
  720. IR1: MT({'': F(['A3'])})
  721. })
  722. }),
  723. }),
  724. ])
  725. self.assertEqual(registry._subscribers,
  726. build_subscribers(
  727. L=self._getMutableListType(),
  728. F=self._getLeafSequenceType(),
  729. MT=self._getMappingType()
  730. ))
  731. def build_provided(P):
  732. return P({
  733. IR0: 6,
  734. IR1: 4,
  735. })
  736. self.assertEqual(registry._provided,
  737. build_provided(P=self._getProvidedType()))
  738. registered = sorted(registry.allSubscriptions())
  739. self.assertEqual(registered, [
  740. ((), IR0, 'A1'),
  741. ((), IR0, 'A2'),
  742. ((IB0,), IR0, 'A1'),
  743. ((IB0,), IR0, 'A2'),
  744. ((IB0,), IR1, 'A3'),
  745. ((IB0,), IR1, 'A4'),
  746. ((IB0, IB1), IR0, 'A1'),
  747. ((IB0, IB2), IR0, 'A2'),
  748. ((IB0, IB2), IR1, 'A4'),
  749. ((IB0, IB3), IR1, 'A3')
  750. ])
  751. # We can duplicate this to another object
  752. registry2 = self._makeOne()
  753. for args in registered:
  754. registry2.subscribe(*args)
  755. self.assertEqual(registry2._subscribers, registry._subscribers)
  756. self.assertEqual(registry2._provided, registry._provided)
  757. # We can change the types and rebuild the data structures.
  758. registry._mappingType = CustomMapping
  759. registry._leafSequenceType = CustomLeafSequence
  760. registry._sequenceType = CustomSequence
  761. registry._providedType = CustomProvided
  762. def addValue(existing, new):
  763. existing = (
  764. existing if existing is not None else CustomLeafSequence()
  765. )
  766. existing.append(new)
  767. return existing
  768. registry._addValueToLeaf = addValue
  769. registry.rebuild()
  770. self.assertEqual(registry._subscribers,
  771. build_subscribers(
  772. L=CustomSequence,
  773. F=CustomLeafSequence,
  774. MT=CustomMapping
  775. ))
  776. class CustomTypesBaseAdapterRegistryTests(BaseAdapterRegistryTests):
  777. """
  778. This class may be extended by other packages to test their own
  779. adapter registries that use custom types. (So be cautious about
  780. breaking changes.)
  781. One known user is ``zope.component.persistentregistry``.
  782. """
  783. def _getMappingType(self):
  784. return CustomMapping
  785. def _getProvidedType(self):
  786. return CustomProvided
  787. def _getMutableListType(self):
  788. return CustomSequence
  789. def _getLeafSequenceType(self):
  790. return CustomLeafSequence
  791. def _getBaseAdapterRegistry(self):
  792. from zope.interface.adapter import BaseAdapterRegistry
  793. class CustomAdapterRegistry(BaseAdapterRegistry):
  794. _mappingType = self._getMappingType()
  795. _sequenceType = self._getMutableListType()
  796. _leafSequenceType = self._getLeafSequenceType()
  797. _providedType = self._getProvidedType()
  798. def _addValueToLeaf(self, existing_leaf_sequence, new_item):
  799. if not existing_leaf_sequence:
  800. existing_leaf_sequence = self._leafSequenceType()
  801. existing_leaf_sequence.append(new_item)
  802. return existing_leaf_sequence
  803. def _removeValueFromLeaf(self, existing_leaf_sequence, to_remove):
  804. without_removed = BaseAdapterRegistry._removeValueFromLeaf(
  805. self,
  806. existing_leaf_sequence,
  807. to_remove)
  808. existing_leaf_sequence[:] = without_removed
  809. assert to_remove not in existing_leaf_sequence
  810. return existing_leaf_sequence
  811. return CustomAdapterRegistry
  812. def assertLeafIdentity(self, leaf1, leaf2):
  813. self.assertIs(leaf1, leaf2)
  814. class LookupBaseFallbackTests(unittest.TestCase):
  815. def _getFallbackClass(self):
  816. from zope.interface.adapter import LookupBaseFallback
  817. return LookupBaseFallback
  818. _getTargetClass = _getFallbackClass
  819. def _makeOne(
  820. self, uc_lookup=None, uc_lookupAll=None, uc_subscriptions=None,
  821. ):
  822. # pylint:disable=function-redefined
  823. if uc_lookup is None:
  824. def uc_lookup(self, required, provided, name):
  825. pass
  826. if uc_lookupAll is None:
  827. def uc_lookupAll(self, required, provided):
  828. raise NotImplementedError()
  829. if uc_subscriptions is None:
  830. def uc_subscriptions(self, required, provided):
  831. raise NotImplementedError()
  832. class Derived(self._getTargetClass()):
  833. _uncached_lookup = uc_lookup
  834. _uncached_lookupAll = uc_lookupAll
  835. _uncached_subscriptions = uc_subscriptions
  836. return Derived()
  837. def test_lookup_w_invalid_name(self):
  838. def _lookup(self, required, provided, name):
  839. self.fail("This should never be called")
  840. lb = self._makeOne(uc_lookup=_lookup)
  841. with self.assertRaises(ValueError):
  842. lb.lookup(('A',), 'B', object())
  843. def test_lookup_miss_no_default(self):
  844. _called_with = []
  845. def _lookup(self, required, provided, name):
  846. _called_with.append((required, provided, name))
  847. lb = self._makeOne(uc_lookup=_lookup)
  848. found = lb.lookup(('A',), 'B', 'C')
  849. self.assertIsNone(found)
  850. self.assertEqual(_called_with, [(('A',), 'B', 'C')])
  851. def test_lookup_miss_w_default(self):
  852. _called_with = []
  853. _default = object()
  854. def _lookup(self, required, provided, name):
  855. _called_with.append((required, provided, name))
  856. lb = self._makeOne(uc_lookup=_lookup)
  857. found = lb.lookup(('A',), 'B', 'C', _default)
  858. self.assertIs(found, _default)
  859. self.assertEqual(_called_with, [(('A',), 'B', 'C')])
  860. def test_lookup_not_cached(self):
  861. _called_with = []
  862. a, b, c = object(), object(), object()
  863. _results = [a, b, c]
  864. def _lookup(self, required, provided, name):
  865. _called_with.append((required, provided, name))
  866. return _results.pop(0)
  867. lb = self._makeOne(uc_lookup=_lookup)
  868. found = lb.lookup(('A',), 'B', 'C')
  869. self.assertIs(found, a)
  870. self.assertEqual(_called_with, [(('A',), 'B', 'C')])
  871. self.assertEqual(_results, [b, c])
  872. def test_lookup_cached(self):
  873. _called_with = []
  874. a, b, c = object(), object(), object()
  875. _results = [a, b, c]
  876. def _lookup(self, required, provided, name):
  877. _called_with.append((required, provided, name))
  878. return _results.pop(0)
  879. lb = self._makeOne(uc_lookup=_lookup)
  880. found = lb.lookup(('A',), 'B', 'C')
  881. found = lb.lookup(('A',), 'B', 'C')
  882. self.assertIs(found, a)
  883. self.assertEqual(_called_with, [(('A',), 'B', 'C')])
  884. self.assertEqual(_results, [b, c])
  885. def test_lookup_not_cached_multi_required(self):
  886. _called_with = []
  887. a, b, c = object(), object(), object()
  888. _results = [a, b, c]
  889. def _lookup(self, required, provided, name):
  890. _called_with.append((required, provided, name))
  891. return _results.pop(0)
  892. lb = self._makeOne(uc_lookup=_lookup)
  893. found = lb.lookup(('A', 'D'), 'B', 'C')
  894. self.assertIs(found, a)
  895. self.assertEqual(_called_with, [(('A', 'D'), 'B', 'C')])
  896. self.assertEqual(_results, [b, c])
  897. def test_lookup_cached_multi_required(self):
  898. _called_with = []
  899. a, b, c = object(), object(), object()
  900. _results = [a, b, c]
  901. def _lookup(self, required, provided, name):
  902. _called_with.append((required, provided, name))
  903. return _results.pop(0)
  904. lb = self._makeOne(uc_lookup=_lookup)
  905. found = lb.lookup(('A', 'D'), 'B', 'C')
  906. found = lb.lookup(('A', 'D'), 'B', 'C')
  907. self.assertIs(found, a)
  908. self.assertEqual(_called_with, [(('A', 'D'), 'B', 'C')])
  909. self.assertEqual(_results, [b, c])
  910. def test_lookup_not_cached_after_changed(self):
  911. _called_with = []
  912. a, b, c = object(), object(), object()
  913. _results = [a, b, c]
  914. def _lookup(self, required, provided, name):
  915. _called_with.append((required, provided, name))
  916. return _results.pop(0)
  917. lb = self._makeOne(uc_lookup=_lookup)
  918. found = lb.lookup(('A',), 'B', 'C')
  919. lb.changed(lb)
  920. found = lb.lookup(('A',), 'B', 'C')
  921. self.assertIs(found, b)
  922. self.assertEqual(_called_with,
  923. [(('A',), 'B', 'C'), (('A',), 'B', 'C')])
  924. self.assertEqual(_results, [c])
  925. def test_lookup1_w_invalid_name(self):
  926. def _lookup(self, required, provided, name):
  927. self.fail("This should never be called")
  928. lb = self._makeOne(uc_lookup=_lookup)
  929. with self.assertRaises(ValueError):
  930. lb.lookup1('A', 'B', object())
  931. def test_lookup1_miss_no_default(self):
  932. _called_with = []
  933. def _lookup(self, required, provided, name):
  934. _called_with.append((required, provided, name))
  935. lb = self._makeOne(uc_lookup=_lookup)
  936. found = lb.lookup1('A', 'B', 'C')
  937. self.assertIsNone(found)
  938. self.assertEqual(_called_with, [(('A',), 'B', 'C')])
  939. def test_lookup1_miss_w_default(self):
  940. _called_with = []
  941. _default = object()
  942. def _lookup(self, required, provided, name):
  943. _called_with.append((required, provided, name))
  944. lb = self._makeOne(uc_lookup=_lookup)
  945. found = lb.lookup1('A', 'B', 'C', _default)
  946. self.assertIs(found, _default)
  947. self.assertEqual(_called_with, [(('A',), 'B', 'C')])
  948. def test_lookup1_miss_w_default_negative_cache(self):
  949. _called_with = []
  950. _default = object()
  951. def _lookup(self, required, provided, name):
  952. _called_with.append((required, provided, name))
  953. lb = self._makeOne(uc_lookup=_lookup)
  954. found = lb.lookup1('A', 'B', 'C', _default)
  955. self.assertIs(found, _default)
  956. found = lb.lookup1('A', 'B', 'C', _default)
  957. self.assertIs(found, _default)
  958. self.assertEqual(_called_with, [(('A',), 'B', 'C')])
  959. def test_lookup1_not_cached(self):
  960. _called_with = []
  961. a, b, c = object(), object(), object()
  962. _results = [a, b, c]
  963. def _lookup(self, required, provided, name):
  964. _called_with.append((required, provided, name))
  965. return _results.pop(0)
  966. lb = self._makeOne(uc_lookup=_lookup)
  967. found = lb.lookup1('A', 'B', 'C')
  968. self.assertIs(found, a)
  969. self.assertEqual(_called_with, [(('A',), 'B', 'C')])
  970. self.assertEqual(_results, [b, c])
  971. def test_lookup1_cached(self):
  972. _called_with = []
  973. a, b, c = object(), object(), object()
  974. _results = [a, b, c]
  975. def _lookup(self, required, provided, name):
  976. _called_with.append((required, provided, name))
  977. return _results.pop(0)
  978. lb = self._makeOne(uc_lookup=_lookup)
  979. found = lb.lookup1('A', 'B', 'C')
  980. found = lb.lookup1('A', 'B', 'C')
  981. self.assertIs(found, a)
  982. self.assertEqual(_called_with, [(('A',), 'B', 'C')])
  983. self.assertEqual(_results, [b, c])
  984. def test_lookup1_not_cached_after_changed(self):
  985. _called_with = []
  986. a, b, c = object(), object(), object()
  987. _results = [a, b, c]
  988. def _lookup(self, required, provided, name):
  989. _called_with.append((required, provided, name))
  990. return _results.pop(0)
  991. lb = self._makeOne(uc_lookup=_lookup)
  992. found = lb.lookup1('A', 'B', 'C')
  993. lb.changed(lb)
  994. found = lb.lookup1('A', 'B', 'C')
  995. self.assertIs(found, b)
  996. self.assertEqual(_called_with,
  997. [(('A',), 'B', 'C'), (('A',), 'B', 'C')])
  998. self.assertEqual(_results, [c])
  999. def test_adapter_hook_w_invalid_name(self):
  1000. req, prv = object(), object()
  1001. lb = self._makeOne()
  1002. with self.assertRaises(ValueError):
  1003. lb.adapter_hook(prv, req, object())
  1004. def test_adapter_hook_miss_no_default(self):
  1005. req, prv = object(), object()
  1006. lb = self._makeOne()
  1007. found = lb.adapter_hook(prv, req, '')
  1008. self.assertIsNone(found)
  1009. def test_adapter_hook_miss_w_default(self):
  1010. req, prv, _default = object(), object(), object()
  1011. lb = self._makeOne()
  1012. found = lb.adapter_hook(prv, req, '', _default)
  1013. self.assertIs(found, _default)
  1014. def test_adapter_hook_hit_factory_returns_None(self):
  1015. _f_called_with = []
  1016. def _factory(context):
  1017. _f_called_with.append(context)
  1018. def _lookup(self, required, provided, name):
  1019. return _factory
  1020. req, prv, _default = object(), object(), object()
  1021. lb = self._makeOne(uc_lookup=_lookup)
  1022. adapted = lb.adapter_hook(prv, req, 'C', _default)
  1023. self.assertIs(adapted, _default)
  1024. self.assertEqual(_f_called_with, [req])
  1025. def test_adapter_hook_hit_factory_returns_adapter(self):
  1026. _f_called_with = []
  1027. _adapter = object()
  1028. def _factory(context):
  1029. _f_called_with.append(context)
  1030. return _adapter
  1031. def _lookup(self, required, provided, name):
  1032. return _factory
  1033. req, prv, _default = object(), object(), object()
  1034. lb = self._makeOne(uc_lookup=_lookup)
  1035. adapted = lb.adapter_hook(prv, req, 'C', _default)
  1036. self.assertIs(adapted, _adapter)
  1037. self.assertEqual(_f_called_with, [req])
  1038. def test_adapter_hook_super_unwraps(self):
  1039. _f_called_with = []
  1040. def _factory(context):
  1041. _f_called_with.append(context)
  1042. return context
  1043. def _lookup(self, required, provided, name=''):
  1044. return _factory
  1045. required = super()
  1046. provided = object()
  1047. lb = self._makeOne(uc_lookup=_lookup)
  1048. adapted = lb.adapter_hook(provided, required)
  1049. self.assertIs(adapted, self)
  1050. self.assertEqual(_f_called_with, [self])
  1051. def test_queryAdapter(self):
  1052. _f_called_with = []
  1053. _adapter = object()
  1054. def _factory(context):
  1055. _f_called_with.append(context)
  1056. return _adapter
  1057. def _lookup(self, required, provided, name):
  1058. return _factory
  1059. req, prv, _default = object(), object(), object()
  1060. lb = self._makeOne(uc_lookup=_lookup)
  1061. adapted = lb.queryAdapter(req, prv, 'C', _default)
  1062. self.assertIs(adapted, _adapter)
  1063. self.assertEqual(_f_called_with, [req])
  1064. def test_lookupAll_uncached(self):
  1065. _called_with = []
  1066. _results = [object(), object(), object()]
  1067. def _lookupAll(self, required, provided):
  1068. _called_with.append((required, provided))
  1069. return tuple(_results)
  1070. lb = self._makeOne(uc_lookupAll=_lookupAll)
  1071. found = lb.lookupAll('A', 'B')
  1072. self.assertEqual(found, tuple(_results))
  1073. self.assertEqual(_called_with, [(('A',), 'B')])
  1074. def test_lookupAll_cached(self):
  1075. _called_with = []
  1076. _results = [object(), object(), object()]
  1077. def _lookupAll(self, required, provided):
  1078. _called_with.append((required, provided))
  1079. return tuple(_results)
  1080. lb = self._makeOne(uc_lookupAll=_lookupAll)
  1081. found = lb.lookupAll('A', 'B')
  1082. found = lb.lookupAll('A', 'B')
  1083. self.assertEqual(found, tuple(_results))
  1084. self.assertEqual(_called_with, [(('A',), 'B')])
  1085. def test_subscriptions_uncached(self):
  1086. _called_with = []
  1087. _results = [object(), object(), object()]
  1088. def _subscriptions(self, required, provided):
  1089. _called_with.append((required, provided))
  1090. return tuple(_results)
  1091. lb = self._makeOne(uc_subscriptions=_subscriptions)
  1092. found = lb.subscriptions('A', 'B')
  1093. self.assertEqual(found, tuple(_results))
  1094. self.assertEqual(_called_with, [(('A',), 'B')])
  1095. def test_subscriptions_cached(self):
  1096. _called_with = []
  1097. _results = [object(), object(), object()]
  1098. def _subscriptions(self, required, provided):
  1099. _called_with.append((required, provided))
  1100. return tuple(_results)
  1101. lb = self._makeOne(uc_subscriptions=_subscriptions)
  1102. found = lb.subscriptions('A', 'B')
  1103. found = lb.subscriptions('A', 'B')
  1104. self.assertEqual(found, tuple(_results))
  1105. self.assertEqual(_called_with, [(('A',), 'B')])
  1106. class LookupBaseTests(LookupBaseFallbackTests,
  1107. OptimizationTestMixin):
  1108. def _getTargetClass(self):
  1109. from zope.interface.adapter import LookupBase
  1110. return LookupBase
  1111. class VerifyingBaseFallbackTests(unittest.TestCase):
  1112. def _getFallbackClass(self):
  1113. from zope.interface.adapter import VerifyingBaseFallback
  1114. return VerifyingBaseFallback
  1115. _getTargetClass = _getFallbackClass
  1116. def _makeOne(self, registry, uc_lookup=None, uc_lookupAll=None,
  1117. uc_subscriptions=None):
  1118. # pylint:disable=function-redefined
  1119. if uc_lookup is None:
  1120. def uc_lookup(self, required, provided, name):
  1121. raise NotImplementedError()
  1122. if uc_lookupAll is None:
  1123. def uc_lookupAll(self, required, provided):
  1124. raise NotImplementedError()
  1125. if uc_subscriptions is None:
  1126. def uc_subscriptions(self, required, provided):
  1127. raise NotImplementedError()
  1128. class Derived(self._getTargetClass()):
  1129. _uncached_lookup = uc_lookup
  1130. _uncached_lookupAll = uc_lookupAll
  1131. _uncached_subscriptions = uc_subscriptions
  1132. def __init__(self, registry):
  1133. super().__init__()
  1134. self._registry = registry
  1135. derived = Derived(registry)
  1136. derived.changed(derived) # init. '_verify_ro' / '_verify_generations'
  1137. return derived
  1138. def _makeRegistry(self, depth):
  1139. class WithGeneration:
  1140. _generation = 1
  1141. class Registry:
  1142. def __init__(self, depth):
  1143. self.ro = [WithGeneration() for i in range(depth)]
  1144. return Registry(depth)
  1145. def test_lookup(self):
  1146. _called_with = []
  1147. a, b, c = object(), object(), object()
  1148. _results = [a, b, c]
  1149. def _lookup(self, required, provided, name):
  1150. _called_with.append((required, provided, name))
  1151. return _results.pop(0)
  1152. reg = self._makeRegistry(3)
  1153. lb = self._makeOne(reg, uc_lookup=_lookup)
  1154. found = lb.lookup(('A',), 'B', 'C')
  1155. found = lb.lookup(('A',), 'B', 'C')
  1156. self.assertIs(found, a)
  1157. self.assertEqual(_called_with, [(('A',), 'B', 'C')])
  1158. self.assertEqual(_results, [b, c])
  1159. reg.ro[1]._generation += 1
  1160. found = lb.lookup(('A',), 'B', 'C')
  1161. self.assertIs(found, b)
  1162. self.assertEqual(_called_with,
  1163. [(('A',), 'B', 'C'), (('A',), 'B', 'C')])
  1164. self.assertEqual(_results, [c])
  1165. def test_lookup1(self):
  1166. _called_with = []
  1167. a, b, c = object(), object(), object()
  1168. _results = [a, b, c]
  1169. def _lookup(self, required, provided, name):
  1170. _called_with.append((required, provided, name))
  1171. return _results.pop(0)
  1172. reg = self._makeRegistry(3)
  1173. lb = self._makeOne(reg, uc_lookup=_lookup)
  1174. found = lb.lookup1('A', 'B', 'C')
  1175. found = lb.lookup1('A', 'B', 'C')
  1176. self.assertIs(found, a)
  1177. self.assertEqual(_called_with, [(('A',), 'B', 'C')])
  1178. self.assertEqual(_results, [b, c])
  1179. reg.ro[1]._generation += 1
  1180. found = lb.lookup1('A', 'B', 'C')
  1181. self.assertIs(found, b)
  1182. self.assertEqual(_called_with,
  1183. [(('A',), 'B', 'C'), (('A',), 'B', 'C')])
  1184. self.assertEqual(_results, [c])
  1185. def test_adapter_hook(self):
  1186. a, b, _c = [object(), object(), object()] # noqa F841
  1187. def _factory1(context):
  1188. return a
  1189. def _factory2(context):
  1190. return b
  1191. def _factory3(context):
  1192. self.fail("This should never be called")
  1193. _factories = [_factory1, _factory2, _factory3]
  1194. def _lookup(self, required, provided, name):
  1195. return _factories.pop(0)
  1196. req, prv, _default = object(), object(), object()
  1197. reg = self._makeRegistry(3)
  1198. lb = self._makeOne(reg, uc_lookup=_lookup)
  1199. adapted = lb.adapter_hook(prv, req, 'C', _default)
  1200. self.assertIs(adapted, a)
  1201. adapted = lb.adapter_hook(prv, req, 'C', _default)
  1202. self.assertIs(adapted, a)
  1203. reg.ro[1]._generation += 1
  1204. adapted = lb.adapter_hook(prv, req, 'C', _default)
  1205. self.assertIs(adapted, b)
  1206. def test_queryAdapter(self):
  1207. a, b, _c = [object(), object(), object()] # noqa F841
  1208. def _factory1(context):
  1209. return a
  1210. def _factory2(context):
  1211. return b
  1212. def _factory3(context):
  1213. self.fail("This should never be called")
  1214. _factories = [_factory1, _factory2, _factory3]
  1215. def _lookup(self, required, provided, name):
  1216. return _factories.pop(0)
  1217. req, prv, _default = object(), object(), object()
  1218. reg = self._makeRegistry(3)
  1219. lb = self._makeOne(reg, uc_lookup=_lookup)
  1220. adapted = lb.queryAdapter(req, prv, 'C', _default)
  1221. self.assertIs(adapted, a)
  1222. adapted = lb.queryAdapter(req, prv, 'C', _default)
  1223. self.assertIs(adapted, a)
  1224. reg.ro[1]._generation += 1
  1225. adapted = lb.adapter_hook(prv, req, 'C', _default)
  1226. self.assertIs(adapted, b)
  1227. def test_lookupAll(self):
  1228. _results_1 = [object(), object(), object()]
  1229. _results_2 = [object(), object(), object()]
  1230. _results = [_results_1, _results_2]
  1231. def _lookupAll(self, required, provided):
  1232. return tuple(_results.pop(0))
  1233. reg = self._makeRegistry(3)
  1234. lb = self._makeOne(reg, uc_lookupAll=_lookupAll)
  1235. found = lb.lookupAll('A', 'B')
  1236. self.assertEqual(found, tuple(_results_1))
  1237. found = lb.lookupAll('A', 'B')
  1238. self.assertEqual(found, tuple(_results_1))
  1239. reg.ro[1]._generation += 1
  1240. found = lb.lookupAll('A', 'B')
  1241. self.assertEqual(found, tuple(_results_2))
  1242. def test_subscriptions(self):
  1243. _results_1 = [object(), object(), object()]
  1244. _results_2 = [object(), object(), object()]
  1245. _results = [_results_1, _results_2]
  1246. def _subscriptions(self, required, provided):
  1247. return tuple(_results.pop(0))
  1248. reg = self._makeRegistry(3)
  1249. lb = self._makeOne(reg, uc_subscriptions=_subscriptions)
  1250. found = lb.subscriptions('A', 'B')
  1251. self.assertEqual(found, tuple(_results_1))
  1252. found = lb.subscriptions('A', 'B')
  1253. self.assertEqual(found, tuple(_results_1))
  1254. reg.ro[1]._generation += 1
  1255. found = lb.subscriptions('A', 'B')
  1256. self.assertEqual(found, tuple(_results_2))
  1257. class VerifyingBaseTests(VerifyingBaseFallbackTests,
  1258. OptimizationTestMixin):
  1259. def _getTargetClass(self):
  1260. from zope.interface.adapter import VerifyingBase
  1261. return VerifyingBase
  1262. class AdapterLookupBaseTests(unittest.TestCase):
  1263. def _getTargetClass(self):
  1264. from zope.interface.adapter import AdapterLookupBase
  1265. return AdapterLookupBase
  1266. def _makeOne(self, registry):
  1267. return self._getTargetClass()(registry)
  1268. def _makeSubregistry(self, *provided):
  1269. class Subregistry:
  1270. def __init__(self):
  1271. self._adapters = []
  1272. self._subscribers = []
  1273. return Subregistry()
  1274. def _makeRegistry(self, *provided):
  1275. class Registry:
  1276. def __init__(self, provided):
  1277. self._provided = provided
  1278. self.ro = []
  1279. return Registry(provided)
  1280. def test_ctor_empty_registry(self):
  1281. registry = self._makeRegistry()
  1282. alb = self._makeOne(registry)
  1283. self.assertEqual(alb._extendors, {})
  1284. def test_ctor_w_registry_provided(self):
  1285. from zope.interface import Interface
  1286. from zope.interface.interface import InterfaceClass
  1287. IFoo = InterfaceClass('IFoo')
  1288. IBar = InterfaceClass('IBar', (IFoo,))
  1289. registry = self._makeRegistry(IFoo, IBar)
  1290. alb = self._makeOne(registry)
  1291. self.assertEqual(sorted(alb._extendors.keys()),
  1292. sorted([IBar, IFoo, Interface]))
  1293. self.assertEqual(alb._extendors[IFoo], [IFoo, IBar])
  1294. self.assertEqual(alb._extendors[IBar], [IBar])
  1295. self.assertEqual(sorted(alb._extendors[Interface]),
  1296. sorted([IFoo, IBar]))
  1297. def test_changed_empty_required(self):
  1298. # ALB.changed expects to call a mixed in changed.
  1299. class Mixin:
  1300. def changed(self, *other):
  1301. pass
  1302. class Derived(self._getTargetClass(), Mixin):
  1303. pass
  1304. registry = self._makeRegistry()
  1305. alb = Derived(registry)
  1306. alb.changed(alb)
  1307. def test_changed_w_required(self):
  1308. # ALB.changed expects to call a mixed in changed.
  1309. class Mixin:
  1310. def changed(self, *other):
  1311. pass
  1312. class Derived(self._getTargetClass(), Mixin):
  1313. pass
  1314. class FauxWeakref:
  1315. _unsub = None
  1316. def __init__(self, here):
  1317. self._here = here
  1318. def __call__(self):
  1319. return self if self._here else None
  1320. def unsubscribe(self, target):
  1321. self._unsub = target
  1322. gone = FauxWeakref(False)
  1323. here = FauxWeakref(True)
  1324. registry = self._makeRegistry()
  1325. alb = Derived(registry)
  1326. alb._required[gone] = 1
  1327. alb._required[here] = 1
  1328. alb.changed(alb)
  1329. self.assertEqual(len(alb._required), 0)
  1330. self.assertEqual(gone._unsub, None)
  1331. self.assertEqual(here._unsub, alb)
  1332. def test_init_extendors_after_registry_update(self):
  1333. from zope.interface import Interface
  1334. from zope.interface.interface import InterfaceClass
  1335. IFoo = InterfaceClass('IFoo')
  1336. IBar = InterfaceClass('IBar', (IFoo,))
  1337. registry = self._makeRegistry()
  1338. alb = self._makeOne(registry)
  1339. registry._provided = [IFoo, IBar]
  1340. alb.init_extendors()
  1341. self.assertEqual(sorted(alb._extendors.keys()),
  1342. sorted([IBar, IFoo, Interface]))
  1343. self.assertEqual(alb._extendors[IFoo], [IFoo, IBar])
  1344. self.assertEqual(alb._extendors[IBar], [IBar])
  1345. self.assertEqual(sorted(alb._extendors[Interface]),
  1346. sorted([IFoo, IBar]))
  1347. def test_add_extendor(self):
  1348. from zope.interface import Interface
  1349. from zope.interface.interface import InterfaceClass
  1350. IFoo = InterfaceClass('IFoo')
  1351. IBar = InterfaceClass('IBar', (IFoo,))
  1352. registry = self._makeRegistry()
  1353. alb = self._makeOne(registry)
  1354. alb.add_extendor(IFoo)
  1355. alb.add_extendor(IBar)
  1356. self.assertEqual(sorted(alb._extendors.keys()),
  1357. sorted([IBar, IFoo, Interface]))
  1358. self.assertEqual(alb._extendors[IFoo], [IFoo, IBar])
  1359. self.assertEqual(alb._extendors[IBar], [IBar])
  1360. self.assertEqual(sorted(alb._extendors[Interface]),
  1361. sorted([IFoo, IBar]))
  1362. def test_remove_extendor(self):
  1363. from zope.interface import Interface
  1364. from zope.interface.interface import InterfaceClass
  1365. IFoo = InterfaceClass('IFoo')
  1366. IBar = InterfaceClass('IBar', (IFoo,))
  1367. registry = self._makeRegistry(IFoo, IBar)
  1368. alb = self._makeOne(registry)
  1369. alb.remove_extendor(IFoo)
  1370. self.assertEqual(sorted(alb._extendors.keys()),
  1371. sorted([IFoo, IBar, Interface]))
  1372. self.assertEqual(alb._extendors[IFoo], [IBar])
  1373. self.assertEqual(alb._extendors[IBar], [IBar])
  1374. self.assertEqual(sorted(alb._extendors[Interface]),
  1375. sorted([IBar]))
  1376. # test '_subscribe' via its callers, '_uncached_lookup', etc.
  1377. def test__uncached_lookup_empty_ro(self):
  1378. from zope.interface.interface import InterfaceClass
  1379. IFoo = InterfaceClass('IFoo')
  1380. IBar = InterfaceClass('IBar', (IFoo,))
  1381. registry = self._makeRegistry()
  1382. alb = self._makeOne(registry)
  1383. result = alb._uncached_lookup((IFoo,), IBar)
  1384. self.assertEqual(result, None)
  1385. self.assertEqual(len(alb._required), 1)
  1386. self.assertIn(IFoo.weakref(), alb._required)
  1387. def test__uncached_lookup_order_miss(self):
  1388. from zope.interface.interface import InterfaceClass
  1389. IFoo = InterfaceClass('IFoo')
  1390. IBar = InterfaceClass('IBar', (IFoo,))
  1391. registry = self._makeRegistry(IFoo, IBar)
  1392. subr = self._makeSubregistry()
  1393. registry.ro.append(subr)
  1394. alb = self._makeOne(registry)
  1395. result = alb._uncached_lookup((IFoo,), IBar)
  1396. self.assertEqual(result, None)
  1397. def test__uncached_lookup_extendors_miss(self):
  1398. from zope.interface.interface import InterfaceClass
  1399. IFoo = InterfaceClass('IFoo')
  1400. IBar = InterfaceClass('IBar', (IFoo,))
  1401. registry = self._makeRegistry()
  1402. subr = self._makeSubregistry()
  1403. subr._adapters = [{}, {}] # utilities, single adapters
  1404. registry.ro.append(subr)
  1405. alb = self._makeOne(registry)
  1406. subr._v_lookup = alb
  1407. result = alb._uncached_lookup((IFoo,), IBar)
  1408. self.assertEqual(result, None)
  1409. def test__uncached_lookup_components_miss_wrong_iface(self):
  1410. from zope.interface.interface import InterfaceClass
  1411. IFoo = InterfaceClass('IFoo')
  1412. IBar = InterfaceClass('IBar', (IFoo,))
  1413. IQux = InterfaceClass('IQux')
  1414. registry = self._makeRegistry(IFoo, IBar)
  1415. subr = self._makeSubregistry()
  1416. irrelevant = object()
  1417. subr._adapters = [ # utilities, single adapters
  1418. {},
  1419. {
  1420. IFoo: {
  1421. IQux: {'': irrelevant},
  1422. },
  1423. },
  1424. ]
  1425. registry.ro.append(subr)
  1426. alb = self._makeOne(registry)
  1427. subr._v_lookup = alb
  1428. result = alb._uncached_lookup((IFoo,), IBar)
  1429. self.assertEqual(result, None)
  1430. def test__uncached_lookup_components_miss_wrong_name(self):
  1431. from zope.interface.interface import InterfaceClass
  1432. IFoo = InterfaceClass('IFoo')
  1433. IBar = InterfaceClass('IBar', (IFoo,))
  1434. registry = self._makeRegistry(IFoo, IBar)
  1435. subr = self._makeSubregistry()
  1436. wrongname = object()
  1437. subr._adapters = [ # utilities, single adapters
  1438. {},
  1439. {
  1440. IFoo: {
  1441. IBar: {'wrongname': wrongname},
  1442. },
  1443. },
  1444. ]
  1445. registry.ro.append(subr)
  1446. alb = self._makeOne(registry)
  1447. subr._v_lookup = alb
  1448. result = alb._uncached_lookup((IFoo,), IBar)
  1449. self.assertEqual(result, None)
  1450. def test__uncached_lookup_simple_hit(self):
  1451. from zope.interface.interface import InterfaceClass
  1452. IFoo = InterfaceClass('IFoo')
  1453. IBar = InterfaceClass('IBar', (IFoo,))
  1454. registry = self._makeRegistry(IFoo, IBar)
  1455. subr = self._makeSubregistry()
  1456. _expected = object()
  1457. subr._adapters = [ # utilities, single adapters
  1458. {},
  1459. {IFoo: {IBar: {'': _expected}}},
  1460. ]
  1461. registry.ro.append(subr)
  1462. alb = self._makeOne(registry)
  1463. subr._v_lookup = alb
  1464. result = alb._uncached_lookup((IFoo,), IBar)
  1465. self.assertIs(result, _expected)
  1466. def test__uncached_lookup_repeated_hit(self):
  1467. from zope.interface.interface import InterfaceClass
  1468. IFoo = InterfaceClass('IFoo')
  1469. IBar = InterfaceClass('IBar', (IFoo,))
  1470. registry = self._makeRegistry(IFoo, IBar)
  1471. subr = self._makeSubregistry()
  1472. _expected = object()
  1473. subr._adapters = [ # utilities, single adapters
  1474. {},
  1475. {IFoo: {IBar: {'': _expected}}},
  1476. ]
  1477. registry.ro.append(subr)
  1478. alb = self._makeOne(registry)
  1479. subr._v_lookup = alb
  1480. result = alb._uncached_lookup((IFoo,), IBar)
  1481. result2 = alb._uncached_lookup((IFoo,), IBar)
  1482. self.assertIs(result, _expected)
  1483. self.assertIs(result2, _expected)
  1484. def test_queryMultiAdaptor_lookup_miss(self):
  1485. from zope.interface.declarations import implementer
  1486. from zope.interface.interface import InterfaceClass
  1487. IFoo = InterfaceClass('IFoo')
  1488. IBar = InterfaceClass('IBar', (IFoo,))
  1489. @implementer(IFoo)
  1490. class Foo:
  1491. pass
  1492. foo = Foo()
  1493. registry = self._makeRegistry()
  1494. subr = self._makeSubregistry()
  1495. subr._adapters = [ # utilities, single adapters
  1496. {},
  1497. {},
  1498. ]
  1499. registry.ro.append(subr)
  1500. alb = self._makeOne(registry)
  1501. alb.lookup = alb._uncached_lookup # provided by derived
  1502. subr._v_lookup = alb
  1503. _default = object()
  1504. result = alb.queryMultiAdapter((foo,), IBar, default=_default)
  1505. self.assertIs(result, _default)
  1506. def test_queryMultiAdapter_errors_on_attribute_access(self):
  1507. # Any error on attribute access previously lead to using the _empty
  1508. # singleton as "requires" argument (See
  1509. # https://github.com/zopefoundation/zope.interface/issues/162)
  1510. # but after https://github.com/zopefoundation/zope.interface/issues/200
  1511. # they get propagated.
  1512. from zope.interface.interface import InterfaceClass
  1513. from __tests__.tests import MissingSomeAttrs
  1514. IFoo = InterfaceClass('IFoo')
  1515. registry = self._makeRegistry()
  1516. alb = self._makeOne(registry)
  1517. alb.lookup = alb._uncached_lookup
  1518. def test(ob):
  1519. return alb.queryMultiAdapter(
  1520. (ob,),
  1521. IFoo,
  1522. )
  1523. MissingSomeAttrs.test_raises(self, test, expected_missing='__class__')
  1524. def test_queryMultiAdaptor_factory_miss(self):
  1525. from zope.interface.declarations import implementer
  1526. from zope.interface.interface import InterfaceClass
  1527. IFoo = InterfaceClass('IFoo')
  1528. IBar = InterfaceClass('IBar', (IFoo,))
  1529. @implementer(IFoo)
  1530. class Foo:
  1531. pass
  1532. foo = Foo()
  1533. registry = self._makeRegistry(IFoo, IBar)
  1534. subr = self._makeSubregistry()
  1535. _called_with = []
  1536. def _factory(context):
  1537. _called_with.append(context)
  1538. subr._adapters = [ # utilities, single adapters
  1539. {},
  1540. {IFoo: {IBar: {'': _factory}}},
  1541. ]
  1542. registry.ro.append(subr)
  1543. alb = self._makeOne(registry)
  1544. alb.lookup = alb._uncached_lookup # provided by derived
  1545. subr._v_lookup = alb
  1546. _default = object()
  1547. result = alb.queryMultiAdapter((foo,), IBar, default=_default)
  1548. self.assertIs(result, _default)
  1549. self.assertEqual(_called_with, [foo])
  1550. def test_queryMultiAdaptor_factory_hit(self):
  1551. from zope.interface.declarations import implementer
  1552. from zope.interface.interface import InterfaceClass
  1553. IFoo = InterfaceClass('IFoo')
  1554. IBar = InterfaceClass('IBar', (IFoo,))
  1555. @implementer(IFoo)
  1556. class Foo:
  1557. pass
  1558. foo = Foo()
  1559. registry = self._makeRegistry(IFoo, IBar)
  1560. subr = self._makeSubregistry()
  1561. _expected = object()
  1562. _called_with = []
  1563. def _factory(context):
  1564. _called_with.append(context)
  1565. return _expected
  1566. subr._adapters = [ # utilities, single adapters
  1567. {},
  1568. {IFoo: {IBar: {'': _factory}}},
  1569. ]
  1570. registry.ro.append(subr)
  1571. alb = self._makeOne(registry)
  1572. alb.lookup = alb._uncached_lookup # provided by derived
  1573. subr._v_lookup = alb
  1574. _default = object()
  1575. result = alb.queryMultiAdapter((foo,), IBar, default=_default)
  1576. self.assertIs(result, _expected)
  1577. self.assertEqual(_called_with, [foo])
  1578. def test_queryMultiAdapter_super_unwraps(self):
  1579. alb = self._makeOne(self._makeRegistry())
  1580. def lookup(*args):
  1581. return factory
  1582. def factory(*args):
  1583. return args
  1584. alb.lookup = lookup
  1585. objects = [
  1586. super(),
  1587. 42,
  1588. "abc",
  1589. super(),
  1590. ]
  1591. result = alb.queryMultiAdapter(objects, None)
  1592. self.assertEqual(result, (
  1593. self,
  1594. 42,
  1595. "abc",
  1596. self,
  1597. ))
  1598. def test__uncached_lookupAll_empty_ro(self):
  1599. from zope.interface.interface import InterfaceClass
  1600. IFoo = InterfaceClass('IFoo')
  1601. IBar = InterfaceClass('IBar', (IFoo,))
  1602. registry = self._makeRegistry()
  1603. alb = self._makeOne(registry)
  1604. result = alb._uncached_lookupAll((IFoo,), IBar)
  1605. self.assertEqual(result, ())
  1606. self.assertEqual(len(alb._required), 1)
  1607. self.assertIn(IFoo.weakref(), alb._required)
  1608. def test__uncached_lookupAll_order_miss(self):
  1609. from zope.interface.interface import InterfaceClass
  1610. IFoo = InterfaceClass('IFoo')
  1611. IBar = InterfaceClass('IBar', (IFoo,))
  1612. registry = self._makeRegistry(IFoo, IBar)
  1613. subr = self._makeSubregistry()
  1614. registry.ro.append(subr)
  1615. alb = self._makeOne(registry)
  1616. subr._v_lookup = alb
  1617. result = alb._uncached_lookupAll((IFoo,), IBar)
  1618. self.assertEqual(result, ())
  1619. def test__uncached_lookupAll_extendors_miss(self):
  1620. from zope.interface.interface import InterfaceClass
  1621. IFoo = InterfaceClass('IFoo')
  1622. IBar = InterfaceClass('IBar', (IFoo,))
  1623. registry = self._makeRegistry()
  1624. subr = self._makeSubregistry()
  1625. subr._adapters = [{}, {}] # utilities, single adapters
  1626. registry.ro.append(subr)
  1627. alb = self._makeOne(registry)
  1628. subr._v_lookup = alb
  1629. result = alb._uncached_lookupAll((IFoo,), IBar)
  1630. self.assertEqual(result, ())
  1631. def test__uncached_lookupAll_components_miss(self):
  1632. from zope.interface.interface import InterfaceClass
  1633. IFoo = InterfaceClass('IFoo')
  1634. IBar = InterfaceClass('IBar', (IFoo,))
  1635. IQux = InterfaceClass('IQux')
  1636. registry = self._makeRegistry(IFoo, IBar)
  1637. subr = self._makeSubregistry()
  1638. irrelevant = object()
  1639. subr._adapters = [ # utilities, single adapters
  1640. {},
  1641. {IFoo: {IQux: {'': irrelevant}}},
  1642. ]
  1643. registry.ro.append(subr)
  1644. alb = self._makeOne(registry)
  1645. subr._v_lookup = alb
  1646. result = alb._uncached_lookupAll((IFoo,), IBar)
  1647. self.assertEqual(result, ())
  1648. def test__uncached_lookupAll_simple_hit(self):
  1649. from zope.interface.interface import InterfaceClass
  1650. IFoo = InterfaceClass('IFoo')
  1651. IBar = InterfaceClass('IBar', (IFoo,))
  1652. registry = self._makeRegistry(IFoo, IBar)
  1653. subr = self._makeSubregistry()
  1654. _expected = object()
  1655. _named = object()
  1656. subr._adapters = [ # utilities, single adapters
  1657. {},
  1658. {IFoo: {IBar: {'': _expected, 'named': _named}}},
  1659. ]
  1660. registry.ro.append(subr)
  1661. alb = self._makeOne(registry)
  1662. subr._v_lookup = alb
  1663. result = alb._uncached_lookupAll((IFoo,), IBar)
  1664. self.assertEqual(sorted(result), [('', _expected), ('named', _named)])
  1665. def test_names(self):
  1666. from zope.interface.interface import InterfaceClass
  1667. IFoo = InterfaceClass('IFoo')
  1668. IBar = InterfaceClass('IBar', (IFoo,))
  1669. registry = self._makeRegistry(IFoo, IBar)
  1670. subr = self._makeSubregistry()
  1671. _expected = object()
  1672. _named = object()
  1673. subr._adapters = [ # utilities, single adapters
  1674. {},
  1675. {IFoo: {IBar: {'': _expected, 'named': _named}}},
  1676. ]
  1677. registry.ro.append(subr)
  1678. alb = self._makeOne(registry)
  1679. alb.lookupAll = alb._uncached_lookupAll
  1680. subr._v_lookup = alb
  1681. result = alb.names((IFoo,), IBar)
  1682. self.assertEqual(sorted(result), ['', 'named'])
  1683. def test__uncached_subscriptions_empty_ro(self):
  1684. from zope.interface.interface import InterfaceClass
  1685. IFoo = InterfaceClass('IFoo')
  1686. IBar = InterfaceClass('IBar', (IFoo,))
  1687. registry = self._makeRegistry()
  1688. alb = self._makeOne(registry)
  1689. result = alb._uncached_subscriptions((IFoo,), IBar)
  1690. self.assertEqual(result, [])
  1691. self.assertEqual(len(alb._required), 1)
  1692. self.assertIn(IFoo.weakref(), alb._required)
  1693. def test__uncached_subscriptions_order_miss(self):
  1694. from zope.interface.interface import InterfaceClass
  1695. IFoo = InterfaceClass('IFoo')
  1696. IBar = InterfaceClass('IBar', (IFoo,))
  1697. registry = self._makeRegistry(IFoo, IBar)
  1698. subr = self._makeSubregistry()
  1699. registry.ro.append(subr)
  1700. alb = self._makeOne(registry)
  1701. subr._v_lookup = alb
  1702. result = alb._uncached_subscriptions((IFoo,), IBar)
  1703. self.assertEqual(result, [])
  1704. def test__uncached_subscriptions_extendors_miss(self):
  1705. from zope.interface.interface import InterfaceClass
  1706. IFoo = InterfaceClass('IFoo')
  1707. IBar = InterfaceClass('IBar', (IFoo,))
  1708. registry = self._makeRegistry()
  1709. subr = self._makeSubregistry()
  1710. subr._subscribers = [{}, {}] # utilities, single adapters
  1711. registry.ro.append(subr)
  1712. alb = self._makeOne(registry)
  1713. subr._v_lookup = alb
  1714. result = alb._uncached_subscriptions((IFoo,), IBar)
  1715. self.assertEqual(result, [])
  1716. def test__uncached_subscriptions_components_miss_wrong_iface(self):
  1717. from zope.interface.interface import InterfaceClass
  1718. IFoo = InterfaceClass('IFoo')
  1719. IBar = InterfaceClass('IBar', (IFoo,))
  1720. IQux = InterfaceClass('IQux')
  1721. registry = self._makeRegistry(IFoo, IBar)
  1722. subr = self._makeSubregistry()
  1723. irrelevant = object()
  1724. subr._subscribers = [ # utilities, single adapters
  1725. {},
  1726. {IFoo: {IQux: {'': irrelevant}}},
  1727. ]
  1728. registry.ro.append(subr)
  1729. alb = self._makeOne(registry)
  1730. subr._v_lookup = alb
  1731. result = alb._uncached_subscriptions((IFoo,), IBar)
  1732. self.assertEqual(result, [])
  1733. def test__uncached_subscriptions_components_miss_wrong_name(self):
  1734. from zope.interface.interface import InterfaceClass
  1735. IFoo = InterfaceClass('IFoo')
  1736. IBar = InterfaceClass('IBar', (IFoo,))
  1737. registry = self._makeRegistry(IFoo, IBar)
  1738. subr = self._makeSubregistry()
  1739. wrongname = object()
  1740. subr._subscribers = [ # utilities, single adapters
  1741. {},
  1742. {IFoo: {IBar: {'wrongname': wrongname}}},
  1743. ]
  1744. registry.ro.append(subr)
  1745. alb = self._makeOne(registry)
  1746. subr._v_lookup = alb
  1747. result = alb._uncached_subscriptions((IFoo,), IBar)
  1748. self.assertEqual(result, [])
  1749. def test__uncached_subscriptions_simple_hit(self):
  1750. from zope.interface.interface import InterfaceClass
  1751. IFoo = InterfaceClass('IFoo')
  1752. IBar = InterfaceClass('IBar', (IFoo,))
  1753. registry = self._makeRegistry(IFoo, IBar)
  1754. subr = self._makeSubregistry()
  1755. class Foo:
  1756. def __lt__(self, other):
  1757. return True
  1758. _exp1, _exp2 = Foo(), Foo()
  1759. subr._subscribers = [ # utilities, single adapters
  1760. {},
  1761. {IFoo: {IBar: {'': (_exp1, _exp2)}}},
  1762. ]
  1763. registry.ro.append(subr)
  1764. alb = self._makeOne(registry)
  1765. subr._v_lookup = alb
  1766. result = alb._uncached_subscriptions((IFoo,), IBar)
  1767. self.assertEqual(sorted(result), sorted([_exp1, _exp2]))
  1768. def test_subscribers_wo_provided(self):
  1769. from zope.interface.declarations import implementer
  1770. from zope.interface.interface import InterfaceClass
  1771. IFoo = InterfaceClass('IFoo')
  1772. IBar = InterfaceClass('IBar', (IFoo,))
  1773. @implementer(IFoo)
  1774. class Foo:
  1775. pass
  1776. foo = Foo()
  1777. registry = self._makeRegistry(IFoo, IBar)
  1778. registry = self._makeRegistry(IFoo, IBar)
  1779. subr = self._makeSubregistry()
  1780. _called = {}
  1781. def _factory1(context):
  1782. _called.setdefault('_factory1', []).append(context)
  1783. def _factory2(context):
  1784. _called.setdefault('_factory2', []).append(context)
  1785. subr._subscribers = [ # utilities, single adapters
  1786. {},
  1787. {IFoo: {None: {'': (_factory1, _factory2)}}},
  1788. ]
  1789. registry.ro.append(subr)
  1790. alb = self._makeOne(registry)
  1791. alb.subscriptions = alb._uncached_subscriptions
  1792. subr._v_lookup = alb
  1793. result = alb.subscribers((foo,), None)
  1794. self.assertEqual(result, ())
  1795. self.assertEqual(_called, {'_factory1': [foo], '_factory2': [foo]})
  1796. def test_subscribers_w_provided(self):
  1797. from zope.interface.declarations import implementer
  1798. from zope.interface.interface import InterfaceClass
  1799. IFoo = InterfaceClass('IFoo')
  1800. IBar = InterfaceClass('IBar', (IFoo,))
  1801. @implementer(IFoo)
  1802. class Foo:
  1803. pass
  1804. foo = Foo()
  1805. registry = self._makeRegistry(IFoo, IBar)
  1806. registry = self._makeRegistry(IFoo, IBar)
  1807. subr = self._makeSubregistry()
  1808. _called = {}
  1809. _exp1, _exp2 = object(), object()
  1810. def _factory1(context):
  1811. _called.setdefault('_factory1', []).append(context)
  1812. return _exp1
  1813. def _factory2(context):
  1814. _called.setdefault('_factory2', []).append(context)
  1815. return _exp2
  1816. def _side_effect_only(context):
  1817. _called.setdefault('_side_effect_only', []).append(context)
  1818. subr._subscribers = [ # utilities, single adapters
  1819. {},
  1820. {IFoo: {IBar: {'': (_factory1, _factory2, _side_effect_only)}}},
  1821. ]
  1822. registry.ro.append(subr)
  1823. alb = self._makeOne(registry)
  1824. alb.subscriptions = alb._uncached_subscriptions
  1825. subr._v_lookup = alb
  1826. result = alb.subscribers((foo,), IBar)
  1827. self.assertEqual(result, [_exp1, _exp2])
  1828. self.assertEqual(
  1829. _called, {
  1830. '_factory1': [foo],
  1831. '_factory2': [foo],
  1832. '_side_effect_only': [foo],
  1833. }
  1834. )
  1835. class VerifyingAdapterRegistryTests(unittest.TestCase):
  1836. # This is also the base for AdapterRegistryTests. That makes the
  1837. # inheritance seems backwards, but even though they implement the
  1838. # same interfaces, VAR and AR each only extend BAR; and neither
  1839. # one will pass the test cases for BAR (it uses a special
  1840. # LookupClass just for the tests).
  1841. def _getTargetClass(self):
  1842. from zope.interface.adapter import VerifyingAdapterRegistry
  1843. return VerifyingAdapterRegistry
  1844. def _makeOne(self, *args, **kw):
  1845. return self._getTargetClass()(*args, **kw)
  1846. def test_verify_object_provides_IAdapterRegistry(self):
  1847. from zope.interface.interfaces import IAdapterRegistry
  1848. from zope.interface.verify import verifyObject
  1849. registry = self._makeOne()
  1850. verifyObject(IAdapterRegistry, registry)
  1851. class AdapterRegistryTests(VerifyingAdapterRegistryTests):
  1852. def _getTargetClass(self):
  1853. from zope.interface.adapter import AdapterRegistry
  1854. return AdapterRegistry
  1855. def test_ctor_no_bases(self):
  1856. ar = self._makeOne()
  1857. self.assertEqual(len(ar._v_subregistries), 0)
  1858. def test_ctor_w_bases(self):
  1859. base = self._makeOne()
  1860. sub = self._makeOne([base])
  1861. self.assertEqual(len(sub._v_subregistries), 0)
  1862. self.assertEqual(len(base._v_subregistries), 1)
  1863. self.assertIn(sub, base._v_subregistries)
  1864. # test _addSubregistry / _removeSubregistry via only caller, _setBases
  1865. def test__setBases_removing_existing_subregistry(self):
  1866. before = self._makeOne()
  1867. after = self._makeOne()
  1868. sub = self._makeOne([before])
  1869. sub.__bases__ = [after]
  1870. self.assertEqual(len(before._v_subregistries), 0)
  1871. self.assertEqual(len(after._v_subregistries), 1)
  1872. self.assertIn(sub, after._v_subregistries)
  1873. def test__setBases_wo_stray_entry(self):
  1874. before = self._makeOne()
  1875. stray = self._makeOne()
  1876. after = self._makeOne()
  1877. sub = self._makeOne([before])
  1878. sub.__dict__['__bases__'].append(stray)
  1879. sub.__bases__ = [after]
  1880. self.assertEqual(len(before._v_subregistries), 0)
  1881. self.assertEqual(len(after._v_subregistries), 1)
  1882. self.assertIn(sub, after._v_subregistries)
  1883. def test__setBases_w_existing_entry_continuing(self):
  1884. before = self._makeOne()
  1885. after = self._makeOne()
  1886. sub = self._makeOne([before])
  1887. sub.__bases__ = [before, after]
  1888. self.assertEqual(len(before._v_subregistries), 1)
  1889. self.assertEqual(len(after._v_subregistries), 1)
  1890. self.assertIn(sub, before._v_subregistries)
  1891. self.assertIn(sub, after._v_subregistries)
  1892. def test_changed_w_subregistries(self):
  1893. base = self._makeOne()
  1894. class Derived:
  1895. _changed = None
  1896. def changed(self, originally_changed):
  1897. self._changed = originally_changed
  1898. derived1, derived2 = Derived(), Derived()
  1899. base._addSubregistry(derived1)
  1900. base._addSubregistry(derived2)
  1901. orig = object()
  1902. base.changed(orig)
  1903. self.assertIs(derived1._changed, orig)
  1904. self.assertIs(derived2._changed, orig)
  1905. class Test_utils(unittest.TestCase):
  1906. def test__convert_None_to_Interface_w_None(self):
  1907. from zope.interface.adapter import _convert_None_to_Interface
  1908. from zope.interface.interface import Interface
  1909. self.assertIs(_convert_None_to_Interface(None), Interface)
  1910. def test__convert_None_to_Interface_w_other(self):
  1911. from zope.interface.adapter import _convert_None_to_Interface
  1912. other = object()
  1913. self.assertIs(_convert_None_to_Interface(other), other)
  1914. def test__normalize_name_str(self):
  1915. from zope.interface.adapter import _normalize_name
  1916. STR = b'str'
  1917. UNICODE = 'str'
  1918. norm = _normalize_name(STR)
  1919. self.assertEqual(norm, UNICODE)
  1920. self.assertIsInstance(norm, type(UNICODE))
  1921. def test__normalize_name_unicode(self):
  1922. from zope.interface.adapter import _normalize_name
  1923. USTR = 'ustr'
  1924. self.assertEqual(_normalize_name(USTR), USTR)
  1925. def test__normalize_name_other(self):
  1926. from zope.interface.adapter import _normalize_name
  1927. for other in 1, 1.0, (), [], {}, object():
  1928. self.assertRaises(TypeError, _normalize_name, other)
  1929. # _lookup, _lookupAll, and _subscriptions tested via their callers
  1930. # (AdapterLookupBase.{lookup,lookupAll,subscriptions}).