test_adapter.py 78 KB

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