123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871 |
- ##############################################################################
- #
- # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
- # All Rights Reserved.
- #
- # This software is subject to the provisions of the Zope Public License,
- # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
- # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
- # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
- # FOR A PARTICULAR PURPOSE.
- #
- ##############################################################################
- """Test Interface implementation
- """
- # Things we let slide because it's a test
- # pylint:disable=protected-access
- # pylint:disable=blacklisted-name
- # pylint:disable=attribute-defined-outside-init
- # pylint:disable=too-many-public-methods
- # pylint:disable=too-many-lines
- # pylint:disable=abstract-method
- # pylint:disable=redefined-builtin
- # pylint:disable=signature-differs
- # pylint:disable=arguments-differ
- # Things you get inheriting from Interface
- # pylint:disable=inherit-non-class
- # pylint:disable=no-self-argument
- # pylint:disable=no-method-argument
- # Things you get using methods of an Interface 'subclass'
- # pylint:disable=no-value-for-parameter
- import unittest
- from __tests__.tests import CleanUp
- from __tests__.tests import MissingSomeAttrs
- from __tests__.tests import OptimizationTestMixin
- from __tests__.tests import SubclassableMixin
- _marker = object()
- class Test_invariant(unittest.TestCase):
- def test_w_single(self):
- from zope.interface.interface import TAGGED_DATA
- from zope.interface.interface import invariant
- def _check(*args, **kw):
- raise NotImplementedError()
- class Foo:
- invariant(_check)
- self.assertEqual(getattr(Foo, TAGGED_DATA, None),
- {'invariants': [_check]})
- def test_w_multiple(self):
- from zope.interface.interface import TAGGED_DATA
- from zope.interface.interface import invariant
- def _check(*args, **kw):
- raise NotImplementedError()
- def _another_check(*args, **kw):
- raise NotImplementedError()
- class Foo:
- invariant(_check)
- invariant(_another_check)
- self.assertEqual(getattr(Foo, TAGGED_DATA, None),
- {'invariants': [_check, _another_check]})
- class Test_taggedValue(unittest.TestCase):
- def test_w_single(self):
- from zope.interface.interface import TAGGED_DATA
- from zope.interface.interface import taggedValue
- class Foo:
- taggedValue('bar', ['baz'])
- self.assertEqual(getattr(Foo, TAGGED_DATA, None),
- {'bar': ['baz']})
- def test_w_multiple(self):
- from zope.interface.interface import TAGGED_DATA
- from zope.interface.interface import taggedValue
- class Foo:
- taggedValue('bar', ['baz'])
- taggedValue('qux', 'spam')
- self.assertEqual(getattr(Foo, TAGGED_DATA, None),
- {'bar': ['baz'], 'qux': 'spam'})
- def test_w_multiple_overwriting(self):
- from zope.interface.interface import TAGGED_DATA
- from zope.interface.interface import taggedValue
- class Foo:
- taggedValue('bar', ['baz'])
- taggedValue('qux', 'spam')
- taggedValue('bar', 'frob')
- self.assertEqual(getattr(Foo, TAGGED_DATA, None),
- {'bar': 'frob', 'qux': 'spam'})
- class ElementTests(unittest.TestCase):
- DEFAULT_NAME = 'AnElement'
- def _getTargetClass(self):
- from zope.interface.interface import Element
- return Element
- def _makeOne(self, name=None):
- if name is None:
- name = self.DEFAULT_NAME
- return self._getTargetClass()(name)
- def test_ctor_defaults(self):
- element = self._makeOne()
- self.assertEqual(element.__name__, self.DEFAULT_NAME)
- self.assertEqual(element.getName(), self.DEFAULT_NAME)
- self.assertEqual(element.__doc__, '')
- self.assertEqual(element.getDoc(), '')
- self.assertEqual(list(element.getTaggedValueTags()), [])
- def test_ctor_no_doc_space_in_name(self):
- element = self._makeOne('An Element')
- self.assertEqual(element.__name__, None)
- self.assertEqual(element.__doc__, 'An Element')
- def test_getTaggedValue_miss(self):
- element = self._makeOne()
- self.assertRaises(KeyError, element.getTaggedValue, 'nonesuch')
- def test_getDirectTaggedValueTags(self):
- element = self._makeOne()
- self.assertEqual([], list(element.getDirectTaggedValueTags()))
- element.setTaggedValue('foo', 'bar')
- self.assertEqual(['foo'], list(element.getDirectTaggedValueTags()))
- def test_queryTaggedValue_miss(self):
- element = self._makeOne()
- self.assertEqual(element.queryTaggedValue('nonesuch'), None)
- def test_queryTaggedValue_miss_w_default(self):
- element = self._makeOne()
- self.assertEqual(element.queryTaggedValue('nonesuch', 'bar'), 'bar')
- def test_getDirectTaggedValue_miss(self):
- element = self._makeOne()
- self.assertRaises(KeyError, element.getDirectTaggedValue, 'nonesuch')
- def test_queryDirectTaggedValue_miss(self):
- element = self._makeOne()
- self.assertEqual(element.queryDirectTaggedValue('nonesuch'), None)
- def test_queryDirectTaggedValue_miss_w_default(self):
- element = self._makeOne()
- self.assertEqual(
- element.queryDirectTaggedValue('nonesuch', 'bar'), 'bar'
- )
- def test_setTaggedValue(self):
- element = self._makeOne()
- element.setTaggedValue('foo', 'bar')
- self.assertEqual(list(element.getTaggedValueTags()), ['foo'])
- self.assertEqual(element.getTaggedValue('foo'), 'bar')
- self.assertEqual(element.queryTaggedValue('foo'), 'bar')
- def test_verifies(self):
- from zope.interface.interfaces import IElement
- from zope.interface.verify import verifyObject
- element = self._makeOne()
- verifyObject(IElement, element)
- class GenericSpecificationBaseTests(unittest.TestCase):
- # Tests that work with both implementations
- def _getFallbackClass(self):
- from zope.interface.interface import SpecificationBasePy
- return SpecificationBasePy
- _getTargetClass = _getFallbackClass
- def _makeOne(self):
- return self._getTargetClass()()
- def test_providedBy_miss(self):
- from zope.interface import interface
- from zope.interface.declarations import _empty
- sb = self._makeOne()
- def _providedBy(obj):
- return _empty
- with _Monkey(interface, providedBy=_providedBy):
- self.assertFalse(sb.providedBy(object()))
- def test_implementedBy_miss(self):
- from zope.interface import interface
- from zope.interface.declarations import _empty
- sb = self._makeOne()
- def _implementedBy(obj):
- return _empty
- with _Monkey(interface, implementedBy=_implementedBy):
- self.assertFalse(sb.implementedBy(object()))
- class SpecificationBaseTests(
- GenericSpecificationBaseTests,
- OptimizationTestMixin,
- SubclassableMixin,
- ):
- # Tests that use the C implementation
- def _getTargetClass(self):
- from zope.interface.interface import SpecificationBase
- return SpecificationBase
- class SpecificationBasePyTests(GenericSpecificationBaseTests):
- # Tests that only work with the Python implementation
- def test___call___miss(self):
- sb = self._makeOne()
- sb._implied = {} # not defined by SpecificationBasePy
- self.assertFalse(sb.isOrExtends(object()))
- def test___call___hit(self):
- sb = self._makeOne()
- testing = object()
- sb._implied = {testing: {}} # not defined by SpecificationBasePy
- self.assertTrue(sb(testing))
- def test_isOrExtends_miss(self):
- sb = self._makeOne()
- sb._implied = {} # not defined by SpecificationBasePy
- self.assertFalse(sb.isOrExtends(object()))
- def test_isOrExtends_hit(self):
- sb = self._makeOne()
- testing = object()
- sb._implied = {testing: {}} # not defined by SpecificationBasePy
- self.assertTrue(sb(testing))
- def test_implementedBy_hit(self):
- from zope.interface import interface
- sb = self._makeOne()
- class _Decl:
- _implied = {sb: {}}
- def _implementedBy(obj):
- return _Decl()
- with _Monkey(interface, implementedBy=_implementedBy):
- self.assertTrue(sb.implementedBy(object()))
- def test_providedBy_hit(self):
- from zope.interface import interface
- sb = self._makeOne()
- class _Decl:
- _implied = {sb: {}}
- def _providedBy(obj):
- return _Decl()
- with _Monkey(interface, providedBy=_providedBy):
- self.assertTrue(sb.providedBy(object()))
- class NameAndModuleComparisonTestsMixin(CleanUp):
- def _makeOneToCompare(self):
- return self._makeOne('a', 'b')
- def __check_NotImplemented_comparison(self, name):
- # Without the correct attributes of __name__ and __module__,
- # comparison switches to the reverse direction.
- import operator
- ib = self._makeOneToCompare()
- op = getattr(operator, name)
- meth = getattr(ib, '__%s__' % name)
- # If either the __name__ or __module__ attribute
- # is missing from the other object, then we return
- # NotImplemented.
- class RaisesErrorOnMissing:
- Exc = AttributeError
- def __getattribute__(self, name):
- try:
- return object.__getattribute__(self, name)
- except AttributeError:
- exc = RaisesErrorOnMissing.Exc
- raise exc(name)
- class RaisesErrorOnModule(RaisesErrorOnMissing):
- def __init__(self):
- self.__name__ = 'foo'
- @property
- def __module__(self):
- raise AttributeError
- class RaisesErrorOnName(RaisesErrorOnMissing):
- def __init__(self):
- self.__module__ = 'foo'
- self.assertEqual(RaisesErrorOnModule().__name__, 'foo')
- self.assertEqual(RaisesErrorOnName().__module__, 'foo')
- with self.assertRaises(AttributeError):
- getattr(RaisesErrorOnModule(), '__module__')
- with self.assertRaises(AttributeError):
- getattr(RaisesErrorOnName(), '__name__')
- for cls in RaisesErrorOnModule, RaisesErrorOnName:
- self.assertIs(meth(cls()), NotImplemented)
- # If the other object has a comparison function, returning
- # NotImplemented means Python calls it.
- class AllowsAnyComparison(RaisesErrorOnMissing):
- def __eq__(self, other):
- return True
- __lt__ = __eq__
- __le__ = __eq__
- __gt__ = __eq__
- __ge__ = __eq__
- __ne__ = __eq__
- self.assertTrue(op(ib, AllowsAnyComparison()))
- self.assertIs(meth(AllowsAnyComparison()), NotImplemented)
- # If it doesn't have the comparison, Python raises a TypeError.
- class AllowsNoComparison:
- __eq__ = None
- __lt__ = __eq__
- __le__ = __eq__
- __gt__ = __eq__
- __ge__ = __eq__
- __ne__ = __eq__
- self.assertIs(meth(AllowsNoComparison()), NotImplemented)
- with self.assertRaises(TypeError):
- op(ib, AllowsNoComparison())
- # Errors besides AttributeError are passed
- class MyException(Exception):
- pass
- RaisesErrorOnMissing.Exc = MyException
- with self.assertRaises(MyException):
- getattr(RaisesErrorOnModule(), '__module__')
- with self.assertRaises(MyException):
- getattr(RaisesErrorOnName(), '__name__')
- for cls in RaisesErrorOnModule, RaisesErrorOnName:
- with self.assertRaises(MyException):
- op(ib, cls())
- with self.assertRaises(MyException):
- meth(cls())
- def test__lt__NotImplemented(self):
- self.__check_NotImplemented_comparison('lt')
- def test__le__NotImplemented(self):
- self.__check_NotImplemented_comparison('le')
- def test__gt__NotImplemented(self):
- self.__check_NotImplemented_comparison('gt')
- def test__ge__NotImplemented(self):
- self.__check_NotImplemented_comparison('ge')
- class InterfaceBaseTestsMixin(NameAndModuleComparisonTestsMixin):
- # Tests for both C and Python implementation
- def _getTargetClass(self):
- raise NotImplementedError
- def _getFallbackClass(self):
- # pylint:disable=no-name-in-module
- from zope.interface.interface import InterfaceBasePy
- return InterfaceBasePy
- def _makeOne(self, object_should_provide=False, name=None, module=None):
- class IB(self._getTargetClass()):
- def _call_conform(self, conform):
- return conform(self)
- def providedBy(self, obj):
- return object_should_provide
- return IB(name, module)
- def test___call___w___conform___returning_value(self):
- ib = self._makeOne(False)
- conformed = object()
- class _Adapted:
- def __conform__(self, iface):
- return conformed
- self.assertIs(ib(_Adapted()), conformed)
- def test___call___wo___conform___ob_no_provides_w_alternate(self):
- ib = self._makeOne(False)
- __traceback_info__ = ib, self._getTargetClass()
- adapted = object()
- alternate = object()
- self.assertIs(ib(adapted, alternate), alternate)
- def test___call___w___conform___ob_no_provides_wo_alternate(self):
- ib = self._makeOne(False)
- with self.assertRaises(TypeError) as exc:
- ib(object())
- self.assertIn('Could not adapt', str(exc.exception))
- def test___call___w_no_conform_catches_only_AttributeError(self):
- MissingSomeAttrs.test_raises(
- self, self._makeOne(), expected_missing='__conform__'
- )
- class InterfaceBaseTests(
- InterfaceBaseTestsMixin,
- OptimizationTestMixin,
- SubclassableMixin,
- unittest.TestCase,
- ):
- # Tests that work with the C implementation
- def _getTargetClass(self):
- from zope.interface.interface import InterfaceBase
- return InterfaceBase
- class InterfaceBasePyTests(InterfaceBaseTestsMixin, unittest.TestCase):
- # Tests that only work with the Python implementation
- _getTargetClass = InterfaceBaseTestsMixin._getFallbackClass
- def test___call___w___conform___miss_ob_provides(self):
- ib = self._makeOne(True)
- class _Adapted:
- def __conform__(self, iface):
- return None
- adapted = _Adapted()
- self.assertIs(ib(adapted), adapted)
- def test___adapt___ob_provides(self):
- ib = self._makeOne(True)
- adapted = object()
- self.assertIs(ib.__adapt__(adapted), adapted)
- def test___adapt___ob_no_provides_uses_hooks(self):
- from zope.interface import interface
- ib = self._makeOne(False)
- adapted = object()
- _missed = []
- def _hook_miss(iface, obj):
- _missed.append((iface, obj))
- def _hook_hit(iface, obj):
- return obj
- with _Monkey(interface, adapter_hooks=[_hook_miss, _hook_hit]):
- self.assertIs(ib.__adapt__(adapted), adapted)
- self.assertEqual(_missed, [(ib, adapted)])
- class SpecificationTests(unittest.TestCase):
- def _getTargetClass(self):
- from zope.interface.interface import Specification
- return Specification
- def _makeOne(self, bases=_marker):
- if bases is _marker:
- return self._getTargetClass()()
- return self._getTargetClass()(bases)
- def test_ctor(self):
- from zope.interface.interface import Interface
- spec = self._makeOne()
- self.assertEqual(spec.__bases__, ())
- self.assertEqual(len(spec._implied), 2)
- self.assertIn(spec, spec._implied)
- self.assertIn(Interface, spec._implied)
- self.assertEqual(len(spec.dependents), 0)
- def test_subscribe_first_time(self):
- spec = self._makeOne()
- dep = DummyDependent()
- spec.subscribe(dep)
- self.assertEqual(len(spec.dependents), 1)
- self.assertEqual(spec.dependents[dep], 1)
- def test_subscribe_again(self):
- spec = self._makeOne()
- dep = DummyDependent()
- spec.subscribe(dep)
- spec.subscribe(dep)
- self.assertEqual(spec.dependents[dep], 2)
- def test_unsubscribe_miss(self):
- spec = self._makeOne()
- dep = DummyDependent()
- self.assertRaises(KeyError, spec.unsubscribe, dep)
- def test_unsubscribe(self):
- spec = self._makeOne()
- dep = DummyDependent()
- spec.subscribe(dep)
- spec.subscribe(dep)
- spec.unsubscribe(dep)
- self.assertEqual(spec.dependents[dep], 1)
- spec.unsubscribe(dep)
- self.assertNotIn(dep, spec.dependents)
- def test___setBases_subscribes_bases_and_notifies_dependents(self):
- from zope.interface.interface import Interface
- spec = self._makeOne()
- dep = DummyDependent()
- spec.subscribe(dep)
- class IFoo(Interface):
- pass
- class IBar(Interface):
- pass
- spec.__bases__ = (IFoo,)
- self.assertEqual(dep._changed, [spec])
- self.assertEqual(IFoo.dependents[spec], 1)
- spec.__bases__ = (IBar,)
- self.assertEqual(IFoo.dependents.get(spec), None)
- self.assertEqual(IBar.dependents[spec], 1)
- def test_changed_clears_volatiles_and_implied(self):
- from zope.interface.interface import Interface
- class IFoo(Interface):
- pass
- spec = self._makeOne()
- spec._v_attrs = 'Foo'
- spec._implied[IFoo] = ()
- spec.changed(spec)
- self.assertIsNone(spec._v_attrs)
- self.assertNotIn(IFoo, spec._implied)
- def test_interfaces_skips_already_seen(self):
- from zope.interface.interface import Interface
- class IFoo(Interface):
- pass
- spec = self._makeOne([IFoo, IFoo])
- self.assertEqual(list(spec.interfaces()), [IFoo])
- def test_extends_strict_wo_self(self):
- from zope.interface.interface import Interface
- class IFoo(Interface):
- pass
- spec = self._makeOne(IFoo)
- self.assertFalse(spec.extends(IFoo, strict=True))
- def test_extends_strict_w_self(self):
- spec = self._makeOne()
- self.assertFalse(spec.extends(spec, strict=True))
- def test_extends_non_strict_w_self(self):
- spec = self._makeOne()
- self.assertTrue(spec.extends(spec, strict=False))
- def test_get_hit_w__v_attrs(self):
- spec = self._makeOne()
- foo = object()
- spec._v_attrs = {'foo': foo}
- self.assertIs(spec.get('foo'), foo)
- def test_get_hit_from_base_wo__v_attrs(self):
- from zope.interface.interface import Attribute
- from zope.interface.interface import Interface
- class IFoo(Interface):
- foo = Attribute('foo')
- class IBar(Interface):
- bar = Attribute('bar')
- spec = self._makeOne([IFoo, IBar])
- self.assertIs(spec.get('foo'), IFoo.get('foo'))
- self.assertIs(spec.get('bar'), IBar.get('bar'))
- def test_multiple_inheritance_no_interfaces(self):
- # If we extend an object that implements interfaces,
- # plus one that doesn't, we do not interject `Interface`
- # early in the resolution order. It stays at the end,
- # like it should.
- # See https://github.com/zopefoundation/zope.interface/issues/8
- from zope.interface.declarations import implementedBy
- from zope.interface.declarations import implementer
- from zope.interface.interface import Interface
- class IDefaultViewName(Interface):
- pass
- class Context:
- pass
- class RDBModel(Context):
- pass
- class IOther(Interface):
- pass
- @implementer(IOther)
- class OtherBase:
- pass
- class Model(OtherBase, Context):
- pass
- self.assertEqual(
- implementedBy(Model).__sro__,
- (
- implementedBy(Model),
- implementedBy(OtherBase),
- IOther,
- implementedBy(Context),
- implementedBy(object),
- Interface, # This used to be wrong, it used to be 2 too high.
- )
- )
- class InterfaceClassTests(unittest.TestCase):
- def _getTargetClass(self):
- from zope.interface.interface import InterfaceClass
- return InterfaceClass
- def _makeOne(self, name='ITest', bases=(), attrs=None, __doc__=None,
- __module__=None):
- return self._getTargetClass()(name, bases, attrs, __doc__, __module__)
- def test_ctor_defaults(self):
- klass = self._getTargetClass()
- inst = klass('ITesting')
- self.assertEqual(inst.__name__, 'ITesting')
- self.assertEqual(inst.__doc__, '')
- self.assertEqual(inst.__bases__, ())
- self.assertEqual(inst.getBases(), ())
- def test_ctor_bad_bases(self):
- klass = self._getTargetClass()
- self.assertRaises(TypeError, klass, 'ITesting', (object(),))
- def test_ctor_w_attrs_attrib_methods(self):
- from zope.interface.interface import Attribute
- from zope.interface.interface import fromFunction
- def _bar():
- """DOCSTRING"""
- ATTRS = {
- 'foo': Attribute('Foo', ''),
- 'bar': fromFunction(_bar),
- }
- klass = self._getTargetClass()
- inst = klass('ITesting', attrs=ATTRS)
- self.assertEqual(inst.__name__, 'ITesting')
- self.assertEqual(inst.__doc__, '')
- self.assertEqual(inst.__bases__, ())
- self.assertEqual(inst.names(), ATTRS.keys())
- def test_ctor_attrs_w___locals__(self):
- ATTRS = {'__locals__': {}}
- klass = self._getTargetClass()
- inst = klass('ITesting', attrs=ATTRS)
- self.assertEqual(inst.__name__, 'ITesting')
- self.assertEqual(inst.__doc__, '')
- self.assertEqual(inst.__bases__, ())
- self.assertEqual(list(inst.names()), [])
- def test_ctor_attrs_w___annotations__(self):
- ATTRS = {'__annotations__': {}}
- klass = self._getTargetClass()
- inst = klass('ITesting', attrs=ATTRS)
- self.assertEqual(inst.__name__, 'ITesting')
- self.assertEqual(inst.__doc__, '')
- self.assertEqual(inst.__bases__, ())
- self.assertEqual(list(inst.names()), [])
- def test_ctor_attrs_w__decorator_non_return(self):
- from zope.interface.interface import _decorator_non_return
- ATTRS = {'dropme': _decorator_non_return}
- klass = self._getTargetClass()
- inst = klass('ITesting', attrs=ATTRS)
- self.assertEqual(inst.__name__, 'ITesting')
- self.assertEqual(inst.__doc__, '')
- self.assertEqual(inst.__bases__, ())
- self.assertEqual(list(inst.names()), [])
- def test_ctor_attrs_w_invalid_attr_type(self):
- from zope.interface.exceptions import InvalidInterface
- ATTRS = {'invalid': object()}
- klass = self._getTargetClass()
- self.assertRaises(InvalidInterface, klass, 'ITesting', attrs=ATTRS)
- def test_ctor_w_explicit___doc__(self):
- ATTRS = {'__doc__': 'ATTR'}
- klass = self._getTargetClass()
- inst = klass('ITesting', attrs=ATTRS, __doc__='EXPLICIT')
- self.assertEqual(inst.__doc__, 'EXPLICIT')
- def test_interfaces(self):
- iface = self._makeOne()
- self.assertEqual(list(iface.interfaces()), [iface])
- def test_getBases(self):
- iface = self._makeOne()
- sub = self._makeOne('ISub', bases=(iface,))
- self.assertEqual(sub.getBases(), (iface,))
- def test_isEqualOrExtendedBy_identity(self):
- iface = self._makeOne()
- self.assertTrue(iface.isEqualOrExtendedBy(iface))
- def test_isEqualOrExtendedBy_subiface(self):
- iface = self._makeOne()
- sub = self._makeOne('ISub', bases=(iface,))
- self.assertTrue(iface.isEqualOrExtendedBy(sub))
- self.assertFalse(sub.isEqualOrExtendedBy(iface))
- def test_isEqualOrExtendedBy_unrelated(self):
- one = self._makeOne('One')
- another = self._makeOne('Another')
- self.assertFalse(one.isEqualOrExtendedBy(another))
- self.assertFalse(another.isEqualOrExtendedBy(one))
- def test_names_w_all_False_ignores_bases(self):
- from zope.interface.interface import Attribute
- from zope.interface.interface import fromFunction
- def _bar():
- """DOCSTRING"""
- BASE_ATTRS = {
- 'foo': Attribute('Foo', ''),
- 'bar': fromFunction(_bar),
- }
- DERIVED_ATTRS = {
- 'baz': Attribute('Baz', ''),
- }
- base = self._makeOne('IBase', attrs=BASE_ATTRS)
- derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
- self.assertEqual(sorted(derived.names(all=False)), ['baz'])
- def test_names_w_all_True_no_bases(self):
- from zope.interface.interface import Attribute
- from zope.interface.interface import fromFunction
- def _bar():
- """DOCSTRING"""
- ATTRS = {
- 'foo': Attribute('Foo', ''),
- 'bar': fromFunction(_bar),
- }
- one = self._makeOne(attrs=ATTRS)
- self.assertEqual(sorted(one.names(all=True)), ['bar', 'foo'])
- def test_names_w_all_True_w_bases_simple(self):
- from zope.interface.interface import Attribute
- from zope.interface.interface import fromFunction
- def _bar():
- """DOCSTRING"""
- BASE_ATTRS = {
- 'foo': Attribute('Foo', ''),
- 'bar': fromFunction(_bar),
- }
- DERIVED_ATTRS = {
- 'baz': Attribute('Baz', ''),
- }
- base = self._makeOne('IBase', attrs=BASE_ATTRS)
- derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
- self.assertEqual(
- sorted(derived.names(all=True)), ['bar', 'baz', 'foo']
- )
- def test_names_w_all_True_bases_w_same_names(self):
- from zope.interface.interface import Attribute
- from zope.interface.interface import fromFunction
- def _bar():
- """DOCSTRING"""
- def _foo():
- """DOCSTRING"""
- BASE_ATTRS = {
- 'foo': Attribute('Foo', ''),
- 'bar': fromFunction(_bar),
- }
- DERIVED_ATTRS = {
- 'foo': fromFunction(_foo),
- 'baz': Attribute('Baz', ''),
- }
- base = self._makeOne('IBase', attrs=BASE_ATTRS)
- derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
- self.assertEqual(sorted(
- derived.names(all=True)), ['bar', 'baz', 'foo']
- )
- def test___iter__(self):
- from zope.interface.interface import Attribute
- from zope.interface.interface import fromFunction
- def _bar():
- """DOCSTRING"""
- def _foo():
- """DOCSTRING"""
- BASE_ATTRS = {
- 'foo': Attribute('Foo', ''),
- 'bar': fromFunction(_bar),
- }
- DERIVED_ATTRS = {
- 'foo': fromFunction(_foo),
- 'baz': Attribute('Baz', ''),
- }
- base = self._makeOne('IBase', attrs=BASE_ATTRS)
- derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
- self.assertEqual(sorted(derived), ['bar', 'baz', 'foo'])
- def test_namesAndDescriptions_w_all_False_ignores_bases(self):
- from zope.interface.interface import Attribute
- from zope.interface.interface import fromFunction
- def _bar():
- """DOCSTRING"""
- BASE_ATTRS = {
- 'foo': Attribute('Foo', ''),
- 'bar': fromFunction(_bar),
- }
- DERIVED_ATTRS = {
- 'baz': Attribute('Baz', ''),
- }
- base = self._makeOne('IBase', attrs=BASE_ATTRS)
- derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
- self.assertEqual(
- sorted(derived.namesAndDescriptions(all=False)), [
- ('baz', DERIVED_ATTRS['baz']),
- ]
- )
- def test_namesAndDescriptions_w_all_True_no_bases(self):
- from zope.interface.interface import Attribute
- from zope.interface.interface import fromFunction
- def _bar():
- """DOCSTRING"""
- ATTRS = {
- 'foo': Attribute('Foo', ''),
- 'bar': fromFunction(_bar),
- }
- one = self._makeOne(attrs=ATTRS)
- self.assertEqual(
- sorted(one.namesAndDescriptions(all=False)), [
- ('bar', ATTRS['bar']),
- ('foo', ATTRS['foo']),
- ]
- )
- def test_namesAndDescriptions_w_all_True_simple(self):
- from zope.interface.interface import Attribute
- from zope.interface.interface import fromFunction
- def _bar():
- """DOCSTRING"""
- BASE_ATTRS = {
- 'foo': Attribute('Foo', ''),
- 'bar': fromFunction(_bar),
- }
- DERIVED_ATTRS = {
- 'baz': Attribute('Baz', ''),
- }
- base = self._makeOne('IBase', attrs=BASE_ATTRS)
- derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
- self.assertEqual(
- sorted(derived.namesAndDescriptions(all=True)), [
- ('bar', BASE_ATTRS['bar']),
- ('baz', DERIVED_ATTRS['baz']),
- ('foo', BASE_ATTRS['foo']),
- ]
- )
- def test_namesAndDescriptions_w_all_True_bases_w_same_names(self):
- from zope.interface.interface import Attribute
- from zope.interface.interface import fromFunction
- def _bar():
- """DOCSTRING"""
- def _foo():
- """DOCSTRING"""
- BASE_ATTRS = {
- 'foo': Attribute('Foo', ''),
- 'bar': fromFunction(_bar),
- }
- DERIVED_ATTRS = {
- 'foo': fromFunction(_foo),
- 'baz': Attribute('Baz', ''),
- }
- base = self._makeOne('IBase', attrs=BASE_ATTRS)
- derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
- self.assertEqual(
- sorted(derived.namesAndDescriptions(all=True)), [
- ('bar', BASE_ATTRS['bar']),
- ('baz', DERIVED_ATTRS['baz']),
- ('foo', DERIVED_ATTRS['foo']),
- ]
- )
- def test_getDescriptionFor_miss(self):
- one = self._makeOne()
- self.assertRaises(KeyError, one.getDescriptionFor, 'nonesuch')
- def test_getDescriptionFor_hit(self):
- from zope.interface.interface import Attribute
- from zope.interface.interface import fromFunction
- def _bar():
- """DOCSTRING"""
- ATTRS = {
- 'foo': Attribute('Foo', ''),
- 'bar': fromFunction(_bar),
- }
- one = self._makeOne(attrs=ATTRS)
- self.assertEqual(one.getDescriptionFor('foo'), ATTRS['foo'])
- self.assertEqual(one.getDescriptionFor('bar'), ATTRS['bar'])
- def test___getitem___miss(self):
- one = self._makeOne()
- def _test():
- return one['nonesuch']
- self.assertRaises(KeyError, _test)
- def test___getitem___hit(self):
- from zope.interface.interface import Attribute
- from zope.interface.interface import fromFunction
- def _bar():
- """DOCSTRING"""
- ATTRS = {
- 'foo': Attribute('Foo', ''),
- 'bar': fromFunction(_bar),
- }
- one = self._makeOne(attrs=ATTRS)
- self.assertEqual(one['foo'], ATTRS['foo'])
- self.assertEqual(one['bar'], ATTRS['bar'])
- def test___contains___miss(self):
- one = self._makeOne()
- self.assertNotIn('nonesuch', one)
- def test___contains___hit(self):
- from zope.interface.interface import Attribute
- from zope.interface.interface import fromFunction
- def _bar():
- """DOCSTRING"""
- ATTRS = {
- 'foo': Attribute('Foo', ''),
- 'bar': fromFunction(_bar),
- }
- one = self._makeOne(attrs=ATTRS)
- self.assertIn('foo', one)
- self.assertIn('bar', one)
- def test_direct_miss(self):
- one = self._makeOne()
- self.assertEqual(one.direct('nonesuch'), None)
- def test_direct_hit_local_miss_bases(self):
- from zope.interface.interface import Attribute
- from zope.interface.interface import fromFunction
- def _bar():
- """DOCSTRING"""
- def _foo():
- """DOCSTRING"""
- BASE_ATTRS = {
- 'foo': Attribute('Foo', ''),
- 'bar': fromFunction(_bar),
- }
- DERIVED_ATTRS = {
- 'foo': fromFunction(_foo),
- 'baz': Attribute('Baz', ''),
- }
- base = self._makeOne('IBase', attrs=BASE_ATTRS)
- derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
- self.assertEqual(derived.direct('foo'), DERIVED_ATTRS['foo'])
- self.assertEqual(derived.direct('baz'), DERIVED_ATTRS['baz'])
- self.assertEqual(derived.direct('bar'), None)
- def test_queryDescriptionFor_miss(self):
- iface = self._makeOne()
- self.assertEqual(iface.queryDescriptionFor('nonesuch'), None)
- def test_queryDescriptionFor_hit(self):
- from zope.interface import Attribute
- ATTRS = {'attr': Attribute('Title', 'Description')}
- iface = self._makeOne(attrs=ATTRS)
- self.assertEqual(iface.queryDescriptionFor('attr'), ATTRS['attr'])
- def test_validateInvariants_pass(self):
- _called_with = []
- def _passable(*args, **kw):
- _called_with.append((args, kw))
- return True
- iface = self._makeOne()
- obj = object()
- iface.setTaggedValue('invariants', [_passable])
- self.assertEqual(iface.validateInvariants(obj), None)
- self.assertEqual(_called_with, [((obj,), {})])
- def test_validateInvariants_fail_wo_errors_passed(self):
- from zope.interface.exceptions import Invalid
- _passable_called_with = []
- def _passable(*args, **kw):
- _passable_called_with.append((args, kw))
- return True
- _fail_called_with = []
- def _fail(*args, **kw):
- _fail_called_with.append((args, kw))
- raise Invalid
- iface = self._makeOne()
- obj = object()
- iface.setTaggedValue('invariants', [_passable, _fail])
- self.assertRaises(Invalid, iface.validateInvariants, obj)
- self.assertEqual(_passable_called_with, [((obj,), {})])
- self.assertEqual(_fail_called_with, [((obj,), {})])
- def test_validateInvariants_fail_w_errors_passed(self):
- from zope.interface.exceptions import Invalid
- _errors = []
- _fail_called_with = []
- def _fail(*args, **kw):
- _fail_called_with.append((args, kw))
- raise Invalid
- iface = self._makeOne()
- obj = object()
- iface.setTaggedValue('invariants', [_fail])
- self.assertRaises(Invalid, iface.validateInvariants, obj, _errors)
- self.assertEqual(_fail_called_with, [((obj,), {})])
- self.assertEqual(len(_errors), 1)
- self.assertIsInstance(_errors[0], Invalid)
- def test_validateInvariants_fail_in_base_wo_errors_passed(self):
- from zope.interface.exceptions import Invalid
- _passable_called_with = []
- def _passable(*args, **kw):
- _passable_called_with.append((args, kw))
- return True
- _fail_called_with = []
- def _fail(*args, **kw):
- _fail_called_with.append((args, kw))
- raise Invalid
- base = self._makeOne('IBase')
- derived = self._makeOne('IDerived', (base,))
- obj = object()
- base.setTaggedValue('invariants', [_fail])
- derived.setTaggedValue('invariants', [_passable])
- self.assertRaises(Invalid, derived.validateInvariants, obj)
- self.assertEqual(_passable_called_with, [((obj,), {})])
- self.assertEqual(_fail_called_with, [((obj,), {})])
- def test_validateInvariants_fail_in_base_w_errors_passed(self):
- from zope.interface.exceptions import Invalid
- _errors = []
- _passable_called_with = []
- def _passable(*args, **kw):
- _passable_called_with.append((args, kw))
- return True
- _fail_called_with = []
- def _fail(*args, **kw):
- _fail_called_with.append((args, kw))
- raise Invalid
- base = self._makeOne('IBase')
- derived = self._makeOne('IDerived', (base,))
- obj = object()
- base.setTaggedValue('invariants', [_fail])
- derived.setTaggedValue('invariants', [_passable])
- self.assertRaises(Invalid, derived.validateInvariants, obj, _errors)
- self.assertEqual(_passable_called_with, [((obj,), {})])
- self.assertEqual(_fail_called_with, [((obj,), {})])
- self.assertEqual(len(_errors), 1)
- self.assertIsInstance(_errors[0], Invalid)
- def test_validateInvariants_inherited_not_called_multiple_times(self):
- _passable_called_with = []
- def _passable(*args, **kw):
- _passable_called_with.append((args, kw))
- return True
- obj = object()
- base = self._makeOne('IBase')
- base.setTaggedValue('invariants', [_passable])
- derived = self._makeOne('IDerived', (base,))
- derived.validateInvariants(obj)
- self.assertEqual(1, len(_passable_called_with))
- def test___reduce__(self):
- iface = self._makeOne('PickleMe')
- self.assertEqual(iface.__reduce__(), 'PickleMe')
- def test___hash___normal(self):
- iface = self._makeOne('HashMe')
- self.assertEqual(
- hash(iface),
- hash(('HashMe', '__tests__.tests.test_interface'))
- )
- def test___hash___missing_required_attrs(self):
- class Derived(self._getTargetClass()):
- def __init__(self): # pylint:disable=super-init-not-called
- pass # Don't call base class.
- derived = Derived()
- with self.assertRaises(AttributeError):
- hash(derived)
- def test_comparison_with_None(self):
- # pylint:disable=singleton-comparison,misplaced-comparison-constant
- iface = self._makeOne()
- self.assertLess(iface, None) # noqa E711
- self.assertLessEqual(iface, None) # noqa E711
- self.assertNotEqual(iface, None) # noqa E711
- self.assertNotEqual(iface, None) # noqa E711
- self.assertFalse(iface >= None) # noqa E711
- self.assertFalse(iface > None) # noqa E711
- self.assertFalse(None < iface) # noqa E711
- self.assertFalse(None <= iface) # noqa E711
- self.assertNotEqual(None, iface) # noqa E711
- self.assertNotEqual(None, iface) # noqa E711
- self.assertGreaterEqual(None, iface) # noqa E711
- self.assertGreater(None, iface) # noqa E711
- def test_comparison_with_same_instance(self):
- # pylint:disable=comparison-with-itself
- iface = self._makeOne()
- self.assertFalse(iface < iface)
- self.assertLessEqual(iface, iface)
- self.assertEqual(iface, iface)
- self.assertEqual(iface, iface)
- self.assertGreaterEqual(iface, iface)
- self.assertFalse(iface > iface)
- def test_comparison_with_same_named_instance_in_other_module(self):
- one = self._makeOne('IName', __module__='__tests__.tests.one')
- other = self._makeOne('IName', __module__='__tests__.tests.other')
- self.assertLess(one, other)
- self.assertFalse(other < one)
- self.assertLessEqual(one, other)
- self.assertFalse(other <= one)
- self.assertNotEqual(one, other)
- self.assertNotEqual(other, one)
- self.assertNotEqual(one, other)
- self.assertNotEqual(other, one)
- self.assertFalse(one >= other)
- self.assertGreaterEqual(other, one)
- self.assertFalse(one > other)
- self.assertGreater(other, one)
- def test_assignment_to__class__(self):
- # https://github.com/zopefoundation/zope.interface/issues/6
- class MyException(Exception):
- pass
- class MyInterfaceClass(self._getTargetClass()):
- def __call__(self, target):
- raise MyException(target)
- IFoo = self._makeOne('IName')
- self.assertIsInstance(IFoo, self._getTargetClass())
- self.assertIs(type(IFoo), self._getTargetClass())
- with self.assertRaises(TypeError):
- IFoo(1)
- IFoo.__class__ = MyInterfaceClass
- self.assertIsInstance(IFoo, MyInterfaceClass)
- self.assertIs(type(IFoo), MyInterfaceClass)
- with self.assertRaises(MyException):
- IFoo(1)
- def test_assignment_to__class__2(self):
- # https://github.com/zopefoundation/zope.interface/issues/6
- # This is essentially a transcription of the
- # test presented in the bug report.
- from zope.interface import Interface
- class MyInterfaceClass(self._getTargetClass()):
- def __call__(self, *args):
- return args
- IFoo = MyInterfaceClass('IFoo', (Interface,))
- self.assertEqual(IFoo(1), (1,))
- class IBar(IFoo):
- pass
- self.assertEqual(IBar(1), (1,))
- class ISpam(Interface):
- pass
- with self.assertRaises(TypeError):
- ISpam()
- ISpam.__class__ = MyInterfaceClass
- self.assertEqual(ISpam(1), (1,))
- def test__module__is_readonly(self):
- inst = self._makeOne()
- with self.assertRaises(AttributeError):
- inst.__module__ = 'different.module'
- class InterfaceTests(unittest.TestCase):
- def test_attributes_link_to_interface(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- class I1(Interface):
- attr = Attribute("My attr")
- self.assertIs(I1['attr'].interface, I1)
- def test_methods_link_to_interface(self):
- from zope.interface import Interface
- class I1(Interface):
- def method(foo, bar, bingo):
- "A method"
- self.assertIs(I1['method'].interface, I1)
- def test_classImplements_simple(self):
- from zope.interface import Interface
- from zope.interface import implementedBy
- from zope.interface import providedBy
- class ICurrent(Interface):
- def method1(a, b):
- """docstring"""
- def method2(a, b):
- """docstring"""
- class IOther(Interface):
- pass
- class Current:
- __implemented__ = ICurrent
- def method1(self, a, b):
- raise NotImplementedError()
- def method2(self, a, b):
- raise NotImplementedError()
- current = Current()
- self.assertTrue(ICurrent.implementedBy(Current))
- self.assertFalse(IOther.implementedBy(Current))
- self.assertEqual(ICurrent, ICurrent)
- self.assertIn(ICurrent, implementedBy(Current))
- self.assertNotIn(IOther, implementedBy(Current))
- self.assertIn(ICurrent, providedBy(current))
- self.assertNotIn(IOther, providedBy(current))
- def test_classImplements_base_not_derived(self):
- from zope.interface import Interface
- from zope.interface import implementedBy
- from zope.interface import providedBy
- class IBase(Interface):
- def method():
- """docstring"""
- class IDerived(IBase):
- pass
- class Current():
- __implemented__ = IBase
- def method(self):
- raise NotImplementedError()
- current = Current()
- self.assertTrue(IBase.implementedBy(Current))
- self.assertFalse(IDerived.implementedBy(Current))
- self.assertIn(IBase, implementedBy(Current))
- self.assertNotIn(IDerived, implementedBy(Current))
- self.assertIn(IBase, providedBy(current))
- self.assertNotIn(IDerived, providedBy(current))
- def test_classImplements_base_and_derived(self):
- from zope.interface import Interface
- from zope.interface import implementedBy
- from zope.interface import providedBy
- class IBase(Interface):
- def method():
- """docstring"""
- class IDerived(IBase):
- pass
- class Current:
- __implemented__ = IDerived
- def method(self):
- raise NotImplementedError()
- current = Current()
- self.assertTrue(IBase.implementedBy(Current))
- self.assertTrue(IDerived.implementedBy(Current))
- self.assertNotIn(IBase, implementedBy(Current))
- self.assertIn(IBase, implementedBy(Current).flattened())
- self.assertIn(IDerived, implementedBy(Current))
- self.assertNotIn(IBase, providedBy(current))
- self.assertIn(IBase, providedBy(current).flattened())
- self.assertIn(IDerived, providedBy(current))
- def test_classImplements_multiple(self):
- from zope.interface import Interface
- from zope.interface import implementedBy
- from zope.interface import providedBy
- class ILeft(Interface):
- def method():
- """docstring"""
- class IRight(ILeft):
- pass
- class Left:
- __implemented__ = ILeft
- def method(self):
- raise NotImplementedError()
- class Right:
- __implemented__ = IRight
- class Ambi(Left, Right):
- pass
- ambi = Ambi()
- self.assertTrue(ILeft.implementedBy(Ambi))
- self.assertTrue(IRight.implementedBy(Ambi))
- self.assertIn(ILeft, implementedBy(Ambi))
- self.assertIn(IRight, implementedBy(Ambi))
- self.assertIn(ILeft, providedBy(ambi))
- self.assertIn(IRight, providedBy(ambi))
- def test_classImplements_multiple_w_explict_implements(self):
- from zope.interface import Interface
- from zope.interface import implementedBy
- from zope.interface import providedBy
- class ILeft(Interface):
- def method():
- """docstring"""
- class IRight(ILeft):
- pass
- class IOther(Interface):
- pass
- class Left():
- __implemented__ = ILeft
- def method(self):
- raise NotImplementedError()
- class Right:
- __implemented__ = IRight
- class Other:
- __implemented__ = IOther
- class Mixed(Left, Right):
- __implemented__ = Left.__implemented__, Other.__implemented__
- mixed = Mixed()
- self.assertTrue(ILeft.implementedBy(Mixed))
- self.assertFalse(IRight.implementedBy(Mixed))
- self.assertTrue(IOther.implementedBy(Mixed))
- self.assertIn(ILeft, implementedBy(Mixed))
- self.assertNotIn(IRight, implementedBy(Mixed))
- self.assertIn(IOther, implementedBy(Mixed))
- self.assertIn(ILeft, providedBy(mixed))
- self.assertNotIn(IRight, providedBy(mixed))
- self.assertIn(IOther, providedBy(mixed))
- def testInterfaceExtendsInterface(self):
- from zope.interface import Interface
- new = Interface.__class__
- FunInterface = new('FunInterface')
- BarInterface = new('BarInterface', (FunInterface,))
- BobInterface = new('BobInterface')
- BazInterface = new('BazInterface', (BobInterface, BarInterface,))
- self.assertTrue(BazInterface.extends(BobInterface))
- self.assertTrue(BazInterface.extends(BarInterface))
- self.assertTrue(BazInterface.extends(FunInterface))
- self.assertFalse(BobInterface.extends(FunInterface))
- self.assertFalse(BobInterface.extends(BarInterface))
- self.assertTrue(BarInterface.extends(FunInterface))
- self.assertFalse(BarInterface.extends(BazInterface))
- def test_verifyClass(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- from zope.interface.verify import verifyClass
- class ICheckMe(Interface):
- attr = Attribute('My attr')
- def method():
- "A method"
- class CheckMe:
- __implemented__ = ICheckMe
- attr = 'value'
- def method(self):
- raise NotImplementedError()
- self.assertTrue(verifyClass(ICheckMe, CheckMe))
- def test_verifyObject(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- from zope.interface.verify import verifyObject
- class ICheckMe(Interface):
- attr = Attribute('My attr')
- def method():
- "A method"
- class CheckMe:
- __implemented__ = ICheckMe
- attr = 'value'
- def method(self):
- raise NotImplementedError()
- check_me = CheckMe()
- self.assertTrue(verifyObject(ICheckMe, check_me))
- def test_interface_object_provides_Interface(self):
- from zope.interface import Interface
- class AnInterface(Interface):
- pass
- self.assertTrue(Interface.providedBy(AnInterface))
- def test_names_simple(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- class ISimple(Interface):
- attr = Attribute('My attr')
- def method():
- """docstring"""
- self.assertEqual(sorted(ISimple.names()), ['attr', 'method'])
- def test_names_derived(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- class IBase(Interface):
- attr = Attribute('My attr')
- def method():
- """docstring"""
- class IDerived(IBase):
- attr2 = Attribute('My attr2')
- def method():
- """docstring"""
- def method2():
- """docstring"""
- self.assertEqual(sorted(IDerived.names()),
- ['attr2', 'method', 'method2'])
- self.assertEqual(sorted(IDerived.names(all=True)),
- ['attr', 'attr2', 'method', 'method2'])
- def test_namesAndDescriptions_simple(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- from zope.interface.interface import Method
- class ISimple(Interface):
- attr = Attribute('My attr')
- def method():
- "My method"
- name_values = sorted(ISimple.namesAndDescriptions())
- self.assertEqual(len(name_values), 2)
- self.assertEqual(name_values[0][0], 'attr')
- self.assertIsInstance(name_values[0][1], Attribute)
- self.assertEqual(name_values[0][1].__name__, 'attr')
- self.assertEqual(name_values[0][1].__doc__, 'My attr')
- self.assertEqual(name_values[1][0], 'method')
- self.assertIsInstance(name_values[1][1], Method)
- self.assertEqual(name_values[1][1].__name__, 'method')
- self.assertEqual(name_values[1][1].__doc__, 'My method')
- def test_namesAndDescriptions_derived(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- from zope.interface.interface import Method
- class IBase(Interface):
- attr = Attribute('My attr')
- def method():
- "My method"
- class IDerived(IBase):
- attr2 = Attribute('My attr2')
- def method():
- "My method, overridden"
- def method2():
- "My method2"
- name_values = sorted(IDerived.namesAndDescriptions())
- self.assertEqual(len(name_values), 3)
- self.assertEqual(name_values[0][0], 'attr2')
- self.assertIsInstance(name_values[0][1], Attribute)
- self.assertEqual(name_values[0][1].__name__, 'attr2')
- self.assertEqual(name_values[0][1].__doc__, 'My attr2')
- self.assertEqual(name_values[1][0], 'method')
- self.assertIsInstance(name_values[1][1], Method)
- self.assertEqual(name_values[1][1].__name__, 'method')
- self.assertEqual(name_values[1][1].__doc__, 'My method, overridden')
- self.assertEqual(name_values[2][0], 'method2')
- self.assertIsInstance(name_values[2][1], Method)
- self.assertEqual(name_values[2][1].__name__, 'method2')
- self.assertEqual(name_values[2][1].__doc__, 'My method2')
- name_values = sorted(IDerived.namesAndDescriptions(all=True))
- self.assertEqual(len(name_values), 4)
- self.assertEqual(name_values[0][0], 'attr')
- self.assertIsInstance(name_values[0][1], Attribute)
- self.assertEqual(name_values[0][1].__name__, 'attr')
- self.assertEqual(name_values[0][1].__doc__, 'My attr')
- self.assertEqual(name_values[1][0], 'attr2')
- self.assertIsInstance(name_values[1][1], Attribute)
- self.assertEqual(name_values[1][1].__name__, 'attr2')
- self.assertEqual(name_values[1][1].__doc__, 'My attr2')
- self.assertEqual(name_values[2][0], 'method')
- self.assertIsInstance(name_values[2][1], Method)
- self.assertEqual(name_values[2][1].__name__, 'method')
- self.assertEqual(name_values[2][1].__doc__, 'My method, overridden')
- self.assertEqual(name_values[3][0], 'method2')
- self.assertIsInstance(name_values[3][1], Method)
- self.assertEqual(name_values[3][1].__name__, 'method2')
- self.assertEqual(name_values[3][1].__doc__, 'My method2')
- def test_getDescriptionFor_nonesuch_no_default(self):
- from zope.interface import Interface
- class IEmpty(Interface):
- pass
- self.assertRaises(KeyError, IEmpty.getDescriptionFor, 'nonesuch')
- def test_getDescriptionFor_simple(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- from zope.interface.interface import Method
- class ISimple(Interface):
- attr = Attribute('My attr')
- def method():
- "My method"
- a_desc = ISimple.getDescriptionFor('attr')
- self.assertIsInstance(a_desc, Attribute)
- self.assertEqual(a_desc.__name__, 'attr')
- self.assertEqual(a_desc.__doc__, 'My attr')
- m_desc = ISimple.getDescriptionFor('method')
- self.assertIsInstance(m_desc, Method)
- self.assertEqual(m_desc.__name__, 'method')
- self.assertEqual(m_desc.__doc__, 'My method')
- def test_getDescriptionFor_derived(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- from zope.interface.interface import Method
- class IBase(Interface):
- attr = Attribute('My attr')
- def method():
- "My method"
- class IDerived(IBase):
- attr2 = Attribute('My attr2')
- def method():
- "My method, overridden"
- def method2():
- "My method2"
- a_desc = IDerived.getDescriptionFor('attr')
- self.assertIsInstance(a_desc, Attribute)
- self.assertEqual(a_desc.__name__, 'attr')
- self.assertEqual(a_desc.__doc__, 'My attr')
- m_desc = IDerived.getDescriptionFor('method')
- self.assertIsInstance(m_desc, Method)
- self.assertEqual(m_desc.__name__, 'method')
- self.assertEqual(m_desc.__doc__, 'My method, overridden')
- a2_desc = IDerived.getDescriptionFor('attr2')
- self.assertIsInstance(a2_desc, Attribute)
- self.assertEqual(a2_desc.__name__, 'attr2')
- self.assertEqual(a2_desc.__doc__, 'My attr2')
- m2_desc = IDerived.getDescriptionFor('method2')
- self.assertIsInstance(m2_desc, Method)
- self.assertEqual(m2_desc.__name__, 'method2')
- self.assertEqual(m2_desc.__doc__, 'My method2')
- def test___getitem__nonesuch(self):
- from zope.interface import Interface
- class IEmpty(Interface):
- pass
- self.assertRaises(KeyError, IEmpty.__getitem__, 'nonesuch')
- def test___getitem__simple(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- from zope.interface.interface import Method
- class ISimple(Interface):
- attr = Attribute('My attr')
- def method():
- "My method"
- a_desc = ISimple['attr']
- self.assertIsInstance(a_desc, Attribute)
- self.assertEqual(a_desc.__name__, 'attr')
- self.assertEqual(a_desc.__doc__, 'My attr')
- m_desc = ISimple['method']
- self.assertIsInstance(m_desc, Method)
- self.assertEqual(m_desc.__name__, 'method')
- self.assertEqual(m_desc.__doc__, 'My method')
- def test___getitem___derived(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- from zope.interface.interface import Method
- class IBase(Interface):
- attr = Attribute('My attr')
- def method():
- "My method"
- class IDerived(IBase):
- attr2 = Attribute('My attr2')
- def method():
- "My method, overridden"
- def method2():
- "My method2"
- a_desc = IDerived['attr']
- self.assertIsInstance(a_desc, Attribute)
- self.assertEqual(a_desc.__name__, 'attr')
- self.assertEqual(a_desc.__doc__, 'My attr')
- m_desc = IDerived['method']
- self.assertIsInstance(m_desc, Method)
- self.assertEqual(m_desc.__name__, 'method')
- self.assertEqual(m_desc.__doc__, 'My method, overridden')
- a2_desc = IDerived['attr2']
- self.assertIsInstance(a2_desc, Attribute)
- self.assertEqual(a2_desc.__name__, 'attr2')
- self.assertEqual(a2_desc.__doc__, 'My attr2')
- m2_desc = IDerived['method2']
- self.assertIsInstance(m2_desc, Method)
- self.assertEqual(m2_desc.__name__, 'method2')
- self.assertEqual(m2_desc.__doc__, 'My method2')
- def test___contains__nonesuch(self):
- from zope.interface import Interface
- class IEmpty(Interface):
- pass
- self.assertNotIn('nonesuch', IEmpty)
- def test___contains__simple(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- class ISimple(Interface):
- attr = Attribute('My attr')
- def method():
- "My method"
- self.assertIn('attr', ISimple)
- self.assertIn('method', ISimple)
- def test___contains__derived(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- class IBase(Interface):
- attr = Attribute('My attr')
- def method():
- "My method"
- class IDerived(IBase):
- attr2 = Attribute('My attr2')
- def method():
- "My method, overridden"
- def method2():
- "My method2"
- self.assertIn('attr', IDerived)
- self.assertIn('method', IDerived)
- self.assertIn('attr2', IDerived)
- self.assertIn('method2', IDerived)
- def test___iter__empty(self):
- from zope.interface import Interface
- class IEmpty(Interface):
- pass
- self.assertEqual(list(IEmpty), [])
- def test___iter__simple(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- class ISimple(Interface):
- attr = Attribute('My attr')
- def method():
- "My method"
- self.assertEqual(sorted(list(ISimple)), ['attr', 'method'])
- def test___iter__derived(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- class IBase(Interface):
- attr = Attribute('My attr')
- def method():
- "My method"
- class IDerived(IBase):
- attr2 = Attribute('My attr2')
- def method():
- "My method, overridden"
- def method2():
- "My method2"
- self.assertEqual(sorted(list(IDerived)),
- ['attr', 'attr2', 'method', 'method2'])
- def test_function_attributes_become_tagged_values(self):
- from zope.interface import Interface
- class ITagMe(Interface):
- def method():
- """docstring"""
- method.optional = 1
- method = ITagMe['method']
- self.assertEqual(method.getTaggedValue('optional'), 1)
- def test___doc___non_element(self):
- from zope.interface import Interface
- class IHaveADocString(Interface):
- "xxx"
- self.assertEqual(IHaveADocString.__doc__, "xxx")
- self.assertEqual(list(IHaveADocString), [])
- def test___doc___as_element(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- class IHaveADocString(Interface):
- "xxx"
- __doc__ = Attribute('the doc')
- self.assertEqual(IHaveADocString.__doc__, "")
- self.assertEqual(list(IHaveADocString), ['__doc__'])
- def _errorsEqual(self, has_invariant, error_len, error_msgs, iface):
- from zope.interface.exceptions import Invalid
- self.assertRaises(Invalid, iface.validateInvariants, has_invariant)
- e = []
- try:
- iface.validateInvariants(has_invariant, e)
- self.fail("validateInvariants should always raise")
- except Invalid as error:
- self.assertEqual(error.args[0], e)
- self.assertEqual(len(e), error_len)
- msgs = [error.args[0] for error in e]
- msgs.sort()
- for msg in msgs:
- self.assertEqual(msg, error_msgs.pop(0))
- def test_invariant_simple(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- from zope.interface import directlyProvides
- from zope.interface import invariant
- class IInvariant(Interface):
- foo = Attribute('foo')
- bar = Attribute('bar; must eval to Boolean True if foo does')
- invariant(_ifFooThenBar)
- class HasInvariant:
- pass
- # set up
- has_invariant = HasInvariant()
- directlyProvides(has_invariant, IInvariant)
- # the tests
- self.assertEqual(IInvariant.getTaggedValue('invariants'),
- [_ifFooThenBar])
- self.assertEqual(IInvariant.validateInvariants(has_invariant), None)
- has_invariant.bar = 27
- self.assertEqual(IInvariant.validateInvariants(has_invariant), None)
- has_invariant.foo = 42
- self.assertEqual(IInvariant.validateInvariants(has_invariant), None)
- del has_invariant.bar
- self._errorsEqual(has_invariant, 1, ['If Foo, then Bar!'],
- IInvariant)
- def test_invariant_nested(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- from zope.interface import directlyProvides
- from zope.interface import invariant
- class IInvariant(Interface):
- foo = Attribute('foo')
- bar = Attribute('bar; must eval to Boolean True if foo does')
- invariant(_ifFooThenBar)
- class ISubInvariant(IInvariant):
- invariant(_barGreaterThanFoo)
- class HasInvariant:
- pass
- # nested interfaces with invariants:
- self.assertEqual(ISubInvariant.getTaggedValue('invariants'),
- [_barGreaterThanFoo])
- has_invariant = HasInvariant()
- directlyProvides(has_invariant, ISubInvariant)
- has_invariant.foo = 42
- # even though the interface has changed, we should still only have one
- # error.
- self._errorsEqual(has_invariant, 1, ['If Foo, then Bar!'],
- ISubInvariant)
- # however, if we set foo to 0 (Boolean False) and bar to a negative
- # number then we'll get the new error
- has_invariant.foo = 2
- has_invariant.bar = 1
- self._errorsEqual(has_invariant, 1,
- ['Please, Boo MUST be greater than Foo!'],
- ISubInvariant)
- # and if we set foo to a positive number and boo to 0, we'll
- # get both errors!
- has_invariant.foo = 1
- has_invariant.bar = 0
- self._errorsEqual(has_invariant, 2,
- ['If Foo, then Bar!',
- 'Please, Boo MUST be greater than Foo!'],
- ISubInvariant)
- # for a happy ending, we'll make the invariants happy
- has_invariant.foo = 1
- has_invariant.bar = 2
- self.assertEqual(IInvariant.validateInvariants(has_invariant), None)
- def test_invariant_mutandis(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- from zope.interface import directlyProvides
- from zope.interface import invariant
- class IInvariant(Interface):
- foo = Attribute('foo')
- bar = Attribute('bar; must eval to Boolean True if foo does')
- invariant(_ifFooThenBar)
- class HasInvariant:
- pass
- # now we'll do two invariants on the same interface,
- # just to make sure that a small
- # multi-invariant interface is at least minimally tested.
- has_invariant = HasInvariant()
- directlyProvides(has_invariant, IInvariant)
- has_invariant.foo = 42
- # if you really need to mutate, then this would be the way to do it.
- # Probably a bad idea, though. :-)
- old_invariants = IInvariant.getTaggedValue('invariants')
- invariants = old_invariants[:]
- invariants.append(_barGreaterThanFoo)
- IInvariant.setTaggedValue('invariants', invariants)
- # even though the interface has changed, we should still only have one
- # error.
- self._errorsEqual(has_invariant, 1, ['If Foo, then Bar!'],
- IInvariant)
- # however, if we set foo to 0 (Boolean False) and bar to a negative
- # number then we'll get the new error
- has_invariant.foo = 2
- has_invariant.bar = 1
- self._errorsEqual(
- has_invariant,
- 1,
- ['Please, Boo MUST be greater than Foo!'],
- IInvariant
- )
- # and if we set foo to a positive number and boo to 0, we'll
- # get both errors!
- has_invariant.foo = 1
- has_invariant.bar = 0
- self._errorsEqual(has_invariant, 2,
- ['If Foo, then Bar!',
- 'Please, Boo MUST be greater than Foo!'],
- IInvariant)
- # for another happy ending, we'll make the invariants happy again
- has_invariant.foo = 1
- has_invariant.bar = 2
- self.assertEqual(IInvariant.validateInvariants(has_invariant), None)
- # clean up
- IInvariant.setTaggedValue('invariants', old_invariants)
- def test___doc___element(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- class IDocstring(Interface):
- "xxx"
- self.assertEqual(IDocstring.__doc__, "xxx")
- self.assertEqual(list(IDocstring), [])
- class IDocstringAndAttribute(Interface):
- "xxx"
- __doc__ = Attribute('the doc')
- self.assertEqual(IDocstringAndAttribute.__doc__, "")
- self.assertEqual(list(IDocstringAndAttribute), ['__doc__'])
- def test_invariant_as_decorator(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- from zope.interface import implementer
- from zope.interface import invariant
- from zope.interface.exceptions import Invalid
- class IRange(Interface):
- min = Attribute("Lower bound")
- max = Attribute("Upper bound")
- @invariant
- def range_invariant(ob):
- if ob.max < ob.min:
- raise Invalid('max < min')
- @implementer(IRange)
- class Range:
- def __init__(self, min, max):
- self.min, self.max = min, max
- IRange.validateInvariants(Range(1, 2))
- IRange.validateInvariants(Range(1, 1))
- try:
- IRange.validateInvariants(Range(2, 1))
- except Invalid as e:
- self.assertEqual(str(e), 'max < min')
- def test_taggedValue(self):
- from zope.interface import Attribute
- from zope.interface import Interface
- from zope.interface import taggedValue
- class ITagged(Interface):
- foo = Attribute('foo')
- bar = Attribute('bar; must eval to Boolean True if foo does')
- taggedValue('qux', 'Spam')
- class IDerived(ITagged):
- taggedValue('qux', 'Spam Spam')
- taggedValue('foo', 'bar')
- class IDerived2(IDerived):
- pass
- self.assertEqual(ITagged.getTaggedValue('qux'), 'Spam')
- self.assertRaises(KeyError, ITagged.getTaggedValue, 'foo')
- self.assertEqual(list(ITagged.getTaggedValueTags()), ['qux'])
- self.assertEqual(IDerived2.getTaggedValue('qux'), 'Spam Spam')
- self.assertEqual(IDerived2.getTaggedValue('foo'), 'bar')
- self.assertEqual(set(IDerived2.getTaggedValueTags()), {'qux', 'foo'})
- def _make_taggedValue_tree(self, base):
- from zope.interface import Attribute
- from zope.interface import taggedValue
- class F(base):
- taggedValue('tag', 'F')
- tag = Attribute('F')
- class E(base):
- taggedValue('tag', 'E')
- tag = Attribute('E')
- class D(base):
- taggedValue('tag', 'D')
- tag = Attribute('D')
- class C(D, F):
- taggedValue('tag', 'C')
- tag = Attribute('C')
- class B(D, E):
- pass
- class A(B, C):
- pass
- return A
- def test_getTaggedValue_follows__iro__(self):
- # And not just looks at __bases__.
- # https://github.com/zopefoundation/zope.interface/issues/190
- from zope.interface import Interface
- # First, confirm that looking at a true class
- # hierarchy follows the __mro__.
- class_A = self._make_taggedValue_tree(object)
- self.assertEqual(class_A.tag.__name__, 'C')
- # Now check that Interface does, both for attributes...
- iface_A = self._make_taggedValue_tree(Interface)
- self.assertEqual(iface_A['tag'].__name__, 'C')
- # ... and for tagged values.
- self.assertEqual(iface_A.getTaggedValue('tag'), 'C')
- self.assertEqual(iface_A.queryTaggedValue('tag'), 'C')
- # Of course setting something lower overrides it.
- assert iface_A.__bases__[0].__name__ == 'B'
- iface_A.__bases__[0].setTaggedValue('tag', 'B')
- self.assertEqual(iface_A.getTaggedValue('tag'), 'B')
- def test_getDirectTaggedValue_ignores__iro__(self):
- # https://github.com/zopefoundation/zope.interface/issues/190
- from zope.interface import Interface
- A = self._make_taggedValue_tree(Interface)
- self.assertIsNone(A.queryDirectTaggedValue('tag'))
- self.assertEqual([], list(A.getDirectTaggedValueTags()))
- with self.assertRaises(KeyError):
- A.getDirectTaggedValue('tag')
- A.setTaggedValue('tag', 'A')
- self.assertEqual(A.queryDirectTaggedValue('tag'), 'A')
- self.assertEqual(A.getDirectTaggedValue('tag'), 'A')
- self.assertEqual(['tag'], list(A.getDirectTaggedValueTags()))
- assert A.__bases__[1].__name__ == 'C'
- C = A.__bases__[1]
- self.assertEqual(C.queryDirectTaggedValue('tag'), 'C')
- self.assertEqual(C.getDirectTaggedValue('tag'), 'C')
- self.assertEqual(['tag'], list(C.getDirectTaggedValueTags()))
- def test_description_cache_management(self):
- # See https://bugs.launchpad.net/zope.interface/+bug/185974
- # There was a bug where the cache used by Specification.get() was not
- # cleared when the bases were changed.
- from zope.interface import Attribute
- from zope.interface import Interface
- class I1(Interface):
- a = Attribute('a')
- class I2(I1):
- pass
- class I3(I2):
- pass
- self.assertIs(I3.get('a'), I1.get('a'))
- I2.__bases__ = (Interface,)
- self.assertIsNone(I3.get('a'))
- def test___call___defers_to___conform___(self):
- from zope.interface import Interface
- from zope.interface import implementer
- class IFoo(Interface):
- pass
- @implementer(IFoo)
- class C:
- def __conform__(self, proto):
- return 0
- self.assertEqual(IFoo(C()), 0)
- def test___call___object_implements(self):
- from zope.interface import Interface
- from zope.interface import implementer
- class IFoo(Interface):
- pass
- @implementer(IFoo)
- class C:
- pass
- c = C()
- self.assertIs(IFoo(c), c)
- def test___call___miss_wo_alternate(self):
- from zope.interface import Interface
- class IFoo(Interface):
- pass
- class C:
- pass
- c = C()
- self.assertRaises(TypeError, IFoo, c)
- def test___call___miss_w_alternate(self):
- from zope.interface import Interface
- class IFoo(Interface):
- pass
- class C:
- pass
- c = C()
- self.assertIs(IFoo(c, self), self)
- def test___call___w_adapter_hook(self):
- from zope.interface import Interface
- from zope.interface.interface import adapter_hooks
- def _miss(iface, obj):
- pass
- def _hit(iface, obj):
- return self
- class IFoo(Interface):
- pass
- class C:
- pass
- c = C()
- old_adapter_hooks = adapter_hooks[:]
- adapter_hooks[:] = [_miss, _hit]
- try:
- self.assertIs(IFoo(c), self)
- finally:
- adapter_hooks[:] = old_adapter_hooks
- def test___call___w_overridden_adapt(self):
- from zope.interface import Interface
- from zope.interface import implementer
- from zope.interface import interfacemethod
- class IFoo(Interface):
- @interfacemethod
- def __adapt__(self, obj):
- return 42
- @implementer(IFoo)
- class Obj:
- pass
- self.assertEqual(42, IFoo(object()))
- # __adapt__ can ignore the fact that the object provides
- # the interface if it chooses.
- self.assertEqual(42, IFoo(Obj()))
- def test___call___w_overridden_adapt_and_conform(self):
- # Conform is first, taking precedence over __adapt__,
- # *if* it returns non-None
- from zope.interface import Interface
- from zope.interface import implementer
- from zope.interface import interfacemethod
- class IAdapt(Interface):
- @interfacemethod
- def __adapt__(self, obj):
- return 42
- class ISimple(Interface):
- """Nothing special."""
- @implementer(IAdapt)
- class Conform24:
- def __conform__(self, iface):
- return 24
- @implementer(IAdapt)
- class ConformNone:
- def __conform__(self, iface):
- return None
- self.assertEqual(42, IAdapt(object()))
- self.assertEqual(24, ISimple(Conform24()))
- self.assertEqual(24, IAdapt(Conform24()))
- with self.assertRaises(TypeError):
- ISimple(ConformNone())
- self.assertEqual(42, IAdapt(ConformNone()))
- def test___call___w_overridden_adapt_call_super(self):
- import sys
- from zope.interface import Interface
- from zope.interface import implementer
- from zope.interface import interfacemethod
- class IFoo(Interface):
- @interfacemethod
- def __adapt__(self, obj):
- if not self.providedBy(obj):
- return 42
- return super().__adapt__(obj)
- @implementer(IFoo)
- class Obj:
- pass
- self.assertEqual(42, IFoo(object()))
- obj = Obj()
- self.assertIs(obj, IFoo(obj))
- def test___adapt___as_method_and_implementation(self):
- from zope.interface import Interface
- from zope.interface import interfacemethod
- class IFoo(Interface):
- @interfacemethod
- def __adapt__(self, obj):
- return 42
- def __adapt__(to_adapt): # noqa F811
- "This is a protocol"
- self.assertEqual(42, IFoo(object()))
- self.assertEqual(IFoo['__adapt__'].getSignatureString(), '(to_adapt)')
- def test___adapt__inheritance_and_type(self):
- from zope.interface import Interface
- from zope.interface import interfacemethod
- class IRoot(Interface):
- """Root"""
- class IWithAdapt(IRoot):
- @interfacemethod
- def __adapt__(self, obj):
- return 42
- class IOther(IRoot):
- """Second branch"""
- class IUnrelated(Interface):
- """Unrelated"""
- class IDerivedAdapt(IUnrelated, IWithAdapt, IOther):
- """Inherits an adapt"""
- # Order of "inheritance" matters here.
- class IDerived2Adapt(IDerivedAdapt):
- """Overrides an inherited custom adapt."""
- @interfacemethod
- def __adapt__(self, obj):
- return 24
- self.assertEqual(42, IDerivedAdapt(object()))
- for iface in IRoot, IWithAdapt, IOther, IUnrelated, IDerivedAdapt:
- self.assertEqual(__name__, iface.__module__)
- for iface in IRoot, IOther, IUnrelated:
- self.assertEqual(type(IRoot), type(Interface))
- # But things that implemented __adapt__ got a new type
- self.assertNotEqual(type(Interface), type(IWithAdapt))
- self.assertEqual(type(IWithAdapt), type(IDerivedAdapt))
- self.assertIsInstance(IWithAdapt, type(Interface))
- self.assertEqual(24, IDerived2Adapt(object()))
- self.assertNotEqual(type(IDerived2Adapt), type(IDerivedAdapt))
- self.assertIsInstance(IDerived2Adapt, type(IDerivedAdapt))
- def test_interfacemethod_is_general(self):
- from zope.interface import Interface
- from zope.interface import interfacemethod
- class IFoo(Interface):
- @interfacemethod
- def __call__(self, obj):
- """Replace an existing method"""
- return 42
- @interfacemethod
- def this_is_new(self):
- return 42
- self.assertEqual(IFoo(self), 42)
- self.assertEqual(IFoo.this_is_new(), 42)
- class AttributeTests(ElementTests):
- DEFAULT_NAME = 'TestAttribute'
- def _getTargetClass(self):
- from zope.interface.interface import Attribute
- return Attribute
- def test__repr__w_interface(self):
- method = self._makeOne()
- method.interface = type(self)
- r = repr(method)
- self.assertTrue(
- r.startswith('<zope.interface.interface.Attribute object at'), r
- )
- self.assertTrue(
- r.endswith(' ' + __name__ + '.AttributeTests.TestAttribute>'), r
- )
- def test__repr__wo_interface(self):
- method = self._makeOne()
- r = repr(method)
- self.assertTrue(
- r.startswith('<zope.interface.interface.Attribute object at'), r
- )
- self.assertTrue(r.endswith(' TestAttribute>'), r)
- def test__str__w_interface(self):
- method = self._makeOne()
- method.interface = type(self)
- r = str(method)
- self.assertEqual(r, __name__ + '.AttributeTests.TestAttribute')
- def test__str__wo_interface(self):
- method = self._makeOne()
- r = str(method)
- self.assertEqual(r, 'TestAttribute')
- class MethodTests(AttributeTests):
- DEFAULT_NAME = 'TestMethod'
- def _getTargetClass(self):
- from zope.interface.interface import Method
- return Method
- def test_optional_as_property(self):
- method = self._makeOne()
- self.assertEqual(method.optional, {})
- method.optional = {'foo': 'bar'}
- self.assertEqual(method.optional, {'foo': 'bar'})
- del method.optional
- self.assertEqual(method.optional, {})
- def test___call___raises_BrokenImplementation(self):
- from zope.interface.exceptions import BrokenImplementation
- method = self._makeOne()
- try:
- method()
- except BrokenImplementation as e:
- self.assertEqual(e.interface, None)
- self.assertEqual(e.name, self.DEFAULT_NAME)
- else:
- self.fail('__call__ should raise BrokenImplementation')
- def test_getSignatureInfo_bare(self):
- method = self._makeOne()
- info = method.getSignatureInfo()
- self.assertEqual(list(info['positional']), [])
- self.assertEqual(list(info['required']), [])
- self.assertEqual(info['optional'], {})
- self.assertEqual(info['varargs'], None)
- self.assertEqual(info['kwargs'], None)
- def test_getSignatureString_bare(self):
- method = self._makeOne()
- self.assertEqual(method.getSignatureString(), '()')
- def test_getSignatureString_w_only_required(self):
- method = self._makeOne()
- method.positional = method.required = ['foo']
- self.assertEqual(method.getSignatureString(), '(foo)')
- def test_getSignatureString_w_optional(self):
- method = self._makeOne()
- method.positional = method.required = ['foo']
- method.optional = {'foo': 'bar'}
- self.assertEqual(method.getSignatureString(), "(foo='bar')")
- def test_getSignatureString_w_varargs(self):
- method = self._makeOne()
- method.varargs = 'args'
- self.assertEqual(method.getSignatureString(), "(*args)")
- def test_getSignatureString_w_kwargs(self):
- method = self._makeOne()
- method.kwargs = 'kw'
- self.assertEqual(method.getSignatureString(), "(**kw)")
- def test__repr__w_interface(self):
- method = self._makeOne()
- method.kwargs = 'kw'
- method.interface = type(self)
- r = repr(method)
- self.assertTrue(
- r.startswith('<zope.interface.interface.Method object at'), r
- )
- self.assertTrue(
- r.endswith(' ' + __name__ + '.MethodTests.TestMethod(**kw)>'), r
- )
- def test__repr__wo_interface(self):
- method = self._makeOne()
- method.kwargs = 'kw'
- r = repr(method)
- self.assertTrue(
- r.startswith('<zope.interface.interface.Method object at'), r
- )
- self.assertTrue(r.endswith(' TestMethod(**kw)>'), r)
- def test__str__w_interface(self):
- method = self._makeOne()
- method.kwargs = 'kw'
- method.interface = type(self)
- r = str(method)
- self.assertEqual(r, __name__ + '.MethodTests.TestMethod(**kw)')
- def test__str__wo_interface(self):
- method = self._makeOne()
- method.kwargs = 'kw'
- r = str(method)
- self.assertEqual(r, 'TestMethod(**kw)')
- class Test_fromFunction(unittest.TestCase):
- def _callFUT(self, *args, **kw):
- from zope.interface.interface import fromFunction
- return fromFunction(*args, **kw)
- def test_bare(self):
- def _func():
- "DOCSTRING"
- method = self._callFUT(_func)
- self.assertEqual(method.getName(), '_func')
- self.assertEqual(method.getDoc(), 'DOCSTRING')
- self.assertEqual(method.interface, None)
- self.assertEqual(list(method.getTaggedValueTags()), [])
- info = method.getSignatureInfo()
- self.assertEqual(list(info['positional']), [])
- self.assertEqual(list(info['required']), [])
- self.assertEqual(info['optional'], {})
- self.assertEqual(info['varargs'], None)
- self.assertEqual(info['kwargs'], None)
- def test_w_interface(self):
- from zope.interface.interface import InterfaceClass
- class IFoo(InterfaceClass):
- pass
- def _func():
- "DOCSTRING"
- method = self._callFUT(_func, interface=IFoo)
- self.assertEqual(method.interface, IFoo)
- def test_w_name(self):
- def _func():
- "DOCSTRING"
- method = self._callFUT(_func, name='anotherName')
- self.assertEqual(method.getName(), 'anotherName')
- def test_w_only_required(self):
- def _func(foo):
- "DOCSTRING"
- method = self._callFUT(_func)
- info = method.getSignatureInfo()
- self.assertEqual(list(info['positional']), ['foo'])
- self.assertEqual(list(info['required']), ['foo'])
- self.assertEqual(info['optional'], {})
- self.assertEqual(info['varargs'], None)
- self.assertEqual(info['kwargs'], None)
- def test_w_optional(self):
- def _func(foo='bar'):
- "DOCSTRING"
- method = self._callFUT(_func)
- info = method.getSignatureInfo()
- self.assertEqual(list(info['positional']), ['foo'])
- self.assertEqual(list(info['required']), [])
- self.assertEqual(info['optional'], {'foo': 'bar'})
- self.assertEqual(info['varargs'], None)
- self.assertEqual(info['kwargs'], None)
- def test_w_optional_self(self):
- # This is a weird case, trying to cover the following code in
- # FUT::
- #
- # nr = na-len(defaults)
- # if nr < 0:
- # defaults=defaults[-nr:]
- # nr = 0
- def _func(self='bar'):
- "DOCSTRING"
- method = self._callFUT(_func, imlevel=1)
- info = method.getSignatureInfo()
- self.assertEqual(list(info['positional']), [])
- self.assertEqual(list(info['required']), [])
- self.assertEqual(info['optional'], {})
- self.assertEqual(info['varargs'], None)
- self.assertEqual(info['kwargs'], None)
- def test_w_varargs(self):
- def _func(*args):
- "DOCSTRING"
- method = self._callFUT(_func)
- info = method.getSignatureInfo()
- self.assertEqual(list(info['positional']), [])
- self.assertEqual(list(info['required']), [])
- self.assertEqual(info['optional'], {})
- self.assertEqual(info['varargs'], 'args')
- self.assertEqual(info['kwargs'], None)
- def test_w_kwargs(self):
- def _func(**kw):
- "DOCSTRING"
- method = self._callFUT(_func)
- info = method.getSignatureInfo()
- self.assertEqual(list(info['positional']), [])
- self.assertEqual(list(info['required']), [])
- self.assertEqual(info['optional'], {})
- self.assertEqual(info['varargs'], None)
- self.assertEqual(info['kwargs'], 'kw')
- def test_full_spectrum(self):
- def _func(
- foo, bar='baz', *args, **kw
- ): # pylint:disable=keyword-arg-before-vararg
- "DOCSTRING"
- method = self._callFUT(_func)
- info = method.getSignatureInfo()
- self.assertEqual(list(info['positional']), ['foo', 'bar'])
- self.assertEqual(list(info['required']), ['foo'])
- self.assertEqual(info['optional'], {'bar': 'baz'})
- self.assertEqual(info['varargs'], 'args')
- self.assertEqual(info['kwargs'], 'kw')
- class Test_fromMethod(unittest.TestCase):
- def _callFUT(self, *args, **kw):
- from zope.interface.interface import fromMethod
- return fromMethod(*args, **kw)
- def test_no_args(self):
- class Foo:
- def bar(self):
- "DOCSTRING"
- method = self._callFUT(Foo.bar)
- self.assertEqual(method.getName(), 'bar')
- self.assertEqual(method.getDoc(), 'DOCSTRING')
- self.assertEqual(method.interface, None)
- self.assertEqual(list(method.getTaggedValueTags()), [])
- info = method.getSignatureInfo()
- self.assertEqual(list(info['positional']), [])
- self.assertEqual(list(info['required']), [])
- self.assertEqual(info['optional'], {})
- self.assertEqual(info['varargs'], None)
- self.assertEqual(info['kwargs'], None)
- def test_full_spectrum(self):
- class Foo:
- def bar(
- self, foo, bar='baz', *args, **kw
- ): # pylint:disable=keyword-arg-before-vararg
- "DOCSTRING"
- method = self._callFUT(Foo.bar)
- info = method.getSignatureInfo()
- self.assertEqual(list(info['positional']), ['foo', 'bar'])
- self.assertEqual(list(info['required']), ['foo'])
- self.assertEqual(info['optional'], {'bar': 'baz'})
- self.assertEqual(info['varargs'], 'args')
- self.assertEqual(info['kwargs'], 'kw')
- def test_w_non_method(self):
- def foo():
- "DOCSTRING"
- method = self._callFUT(foo)
- self.assertEqual(method.getName(), 'foo')
- self.assertEqual(method.getDoc(), 'DOCSTRING')
- self.assertEqual(method.interface, None)
- self.assertEqual(list(method.getTaggedValueTags()), [])
- info = method.getSignatureInfo()
- self.assertEqual(list(info['positional']), [])
- self.assertEqual(list(info['required']), [])
- self.assertEqual(info['optional'], {})
- self.assertEqual(info['varargs'], None)
- self.assertEqual(info['kwargs'], None)
- class DummyDependent:
- def __init__(self):
- self._changed = []
- def changed(self, originally_changed):
- self._changed.append(originally_changed)
- def _barGreaterThanFoo(obj):
- from zope.interface.exceptions import Invalid
- foo = getattr(obj, 'foo', None)
- bar = getattr(obj, 'bar', None)
- if foo is not None and isinstance(foo, type(bar)):
- # type checking should be handled elsewhere (like, say,
- # schema); these invariants should be intra-interface
- # constraints. This is a hacky way to do it, maybe, but you
- # get the idea
- if not bar > foo:
- raise Invalid('Please, Boo MUST be greater than Foo!')
- def _ifFooThenBar(obj):
- from zope.interface.exceptions import Invalid
- if getattr(obj, 'foo', None) and not getattr(obj, 'bar', None):
- raise Invalid('If Foo, then Bar!')
- class _Monkey:
- # context-manager for replacing module names in the scope of a test.
- def __init__(self, module, **kw):
- self.module = module
- self.to_restore = {key: getattr(module, key) for key in kw}
- for key, value in kw.items():
- setattr(module, key, value)
- def __enter__(self):
- return self
- def __exit__(self, exc_type, exc_val, exc_tb):
- for key, value in self.to_restore.items():
- setattr(self.module, key, value)
- class TestTypeAnnotations(unittest.TestCase):
- """Test using Interfaces in type annotations."""
- def test___or__(self):
- from typing import Optional
- from typing import Union
- from zope.interface import Interface
- class I1(Interface):
- pass
- class I2(Interface):
- pass
- class B:
- a: I1 | None
- b: I1 | I2
- self.assertEqual(
- B.__annotations__, {'a': Optional[I1], 'b': Union[I1, I2]})
- def test___ror__(self):
- from typing import Optional
- from typing import Union
- from zope.interface import Interface
- class I1(Interface):
- pass
- class A:
- pass
- class B:
- a: None | I1
- b: A | I1
- self.assertEqual(
- B.__annotations__, {'a': Optional[I1], 'b': Union[A, I1]})
|