diff options
| author | Jim Fulton <jim@zope.com> | 2006-03-11 17:41:29 +0000 |
|---|---|---|
| committer | Jim Fulton <jim@zope.com> | 2006-03-11 17:41:29 +0000 |
| commit | e1951a321d684404c0c34a557ee277ff7d6f3618 (patch) | |
| tree | 09c206f6bd6ffda8a0100fa5b98fd65472588ab1 | |
| parent | 8f9bf8ba2f7f9449cdd734c91ee081fd85cb2d06 (diff) | |
| download | zope-interface-e1951a321d684404c0c34a557ee277ff7d6f3618.tar.gz | |
Removed interface copy
45 files changed, 1 insertions, 10372 deletions
diff --git a/src/zope/__init__.py b/src/zope/__init__.py index 792d600..de40ea7 100644 --- a/src/zope/__init__.py +++ b/src/zope/__init__.py @@ -1 +1 @@ -# +__import__('pkg_resources').declare_namespace(__name__) diff --git a/src/zope/interface/DEPENDENCIES.cfg b/src/zope/interface/DEPENDENCIES.cfg deleted file mode 100644 index ea3a37f..0000000 --- a/src/zope/interface/DEPENDENCIES.cfg +++ /dev/null @@ -1 +0,0 @@ -zope.testing diff --git a/src/zope/interface/PUBLICATION.cfg b/src/zope/interface/PUBLICATION.cfg deleted file mode 100644 index d5ab950..0000000 --- a/src/zope/interface/PUBLICATION.cfg +++ /dev/null @@ -1,8 +0,0 @@ -Metadata-Version: 1.0 -Name: zope.interface -Summary: Zope 3 Interface Infrastructure -Author: Zope Corporation and Contributors -Author-email: zope3-dev@zope.org -License: ZPL 2.1 -Description: - The implementation of interface definitions for Zope 3. diff --git a/src/zope/interface/README.ru.txt b/src/zope/interface/README.ru.txt deleted file mode 100644 index 69a2f73..0000000 --- a/src/zope/interface/README.ru.txt +++ /dev/null @@ -1,689 +0,0 @@ -========== -Интерфейсы -========== - -.. contents:: - -Интерфейсы - это объекты специфицирующие (документирующие) внешнее поведение -объектов которые их "предоставляют". Интерфейсы определяют поведение через -следующие составляющие: - -- Неформальную документацию в строках документации - -- Определения атрибутов - -- Инварианты, представленные условиями которые должны быть соблюдены - для объектов предоставляющих интерфейс - -Определения атрибутов описывают конкретные атрибуты. Они определяют -имя атрибута и предоставляют документацию и ограничения для значений -атрибута. Определения атрибутов могут быть заданы несколькими путями -как мы увидим ниже. - -Определение интерфейсов -======================= - -Интерфейсы определяются с использованием ключевого слова class: - - >>> import zope.interface - >>> class IFoo(zope.interface.Interface): - ... """Foo blah blah""" - ... - ... x = zope.interface.Attribute("""X blah blah""") - ... - ... def bar(q, r=None): - ... """bar blah blah""" - -В примере выше мы создали интерфейс `IFoo`. Мы наследуем его от -класса `zope.interface.Interface`, который является родительским интерфейсом -для всех интерфейсов, как `object` - это родительский класс для всех новых -классов [#create]_. Данный интерфейс не является классом, а является -Интерфейсом, экземпляром `InterfaceClass`:: - - >>> type(IFoo) - <class 'zope.interface.interface.InterfaceClass'> - -Мы можем запросить у интерфейса его документацию:: - - >>> IFoo.__doc__ - 'Foo blah blah' - -и его имя:: - - >>> IFoo.__name__ - 'IFoo' - -и даже модуль в котором он определен:: - - >>> IFoo.__module__ - '__main__' - -Наш интерфейс определяет два атрибута: - -`x` - Это простейшая форма определения атрибутов. Определяются имя - и строка документации. Формально здесь не определяется ничего более. - -`bar` - Это метод. Методы определяются как обычные функции. Метод - это просто - атрибут который должен быть вызываемым с указанием сигнатуры, - предоставляемой определением функции. - - Надо отметить, что аргумент `self` не указывается для `bar`. Интерфейс - документирует как объект *используется*. Когда методы экземпляров классов - вызываются мы не передаем аргумент `self`, таким образом аргумент `self` - не включается и в сигнатуру интерфейса. Аргумент `self` в методах - экземпляров классов на самом деле деталь реализации экземпляров классов - в Python. Другие объекты кроме экземпляров классов могут предоставлять - интерфейсы и их методы могут не быть методами экземпляров классов. Для - примера модули могут предоставлять интерфейсы и их методы обычно просто - функции. Даже экземпляры могут иметь методы не являющиеся методами - экземпляров класса. - -Мы можем получить доступ к атрибутам определенным интерфейсом используя -синтакс доступа к элементам массива:: - - >>> x = IFoo['x'] - >>> type(x) - <class 'zope.interface.interface.Attribute'> - >>> x.__name__ - 'x' - >>> x.__doc__ - 'X blah blah' - - >>> IFoo.get('x').__name__ - 'x' - - >>> IFoo.get('y') - -Можно использовать `in` для определения содержит ли интерфейс -определенное имя:: - - >>> 'x' in IFoo - True - -Мы можем использовать итератор для интерфейсов что бы получить все имена -которые интерфейсы определяют:: - - >>> names = list(IFoo) - >>> names.sort() - >>> names - ['bar', 'x'] - -Надо помнить, что интерфейсы не являются классами. Мы не можем получить -доступ к определениям атрибутов через доступ к атрибутам интерфейсов:: - - >>> IFoo.x - Traceback (most recent call last): - File "<stdin>", line 1, in ? - AttributeError: 'InterfaceClass' object has no attribute 'x' - -Методы также предоставляют доступ к сигнатуре метода:: - - >>> bar = IFoo['bar'] - >>> bar.getSignatureString() - '(q, r=None)' - - (Методы должны иметь лучший API. Это то, что должно быть улучшено.) - -Объявление интерфейсов -====================== - -Определив интерфес мы можем теперь *объявить*, что объекты предоставляют их. -Перед описанием деталей определим некоторые термины: - -*предоставлять* - Мы говорим, что объекты *предоставляют* интерфейсы. Если объект - предоставляет интерфейс, тогда интерфейс специфицирует поведение объекта. - Другими словами, интерфейсы специфицируют поведение объектов которые - предоставляют их. - -*реализовать* - Мы обычно говорим что классы *реализуют* интерфейсы. Если класс - реализует интерфейс, тогда экземпляры этого класса предоставляют - данный интерфейс. Объекты предоставляют интерфейсы которые их классы - реализуют [#factory]_. (Объекты также могут предоставлять интерфейсы напрямую - плюс к тем которые реализуют их классы.) - - Важно помнить, что классы обычно не предоставляют интерфейсы которые - они реализуют. - - Мы можем обобщить это до фабрик. Для любого вызываемого объекта мы можем - объявить что он производит объекты которые предоставляют какие-либо - интерфейсы сказав, что фабрика реализует данные интерфейсы. - -Теперь после того как мы определили эти термины мы можем поговорить об -API для объявления интерфейсов. - -Обявление реализуемых интерфесов --------------------------------- - -Наиболее часто используемый путь для объявления интерфейсов - это использование -функции implements в определении класса:: - - >>> class Foo: - ... zope.interface.implements(IFoo) - ... - ... def __init__(self, x=None): - ... self.x = x - ... - ... def bar(self, q, r=None): - ... return q, r, self.x - ... - ... def __repr__(self): - ... return "Foo(%s)" % self.x - -В этом примере мы объявили, что `Foo` реализует `IFoo`. Это значит, что -экземпляры `Foo` предоставляют `IFoo`. После данного объявления есть -несколько путей для анализа объявлений. Во-первых мы можем спросить -что интерфейс реализован классом:: - - >>> IFoo.implementedBy(Foo) - True - -Также мы можем спросить если интерфейс предоставляется объектами класса:: - - >>> foo = Foo() - >>> IFoo.providedBy(foo) - True - -Конечно `Foo` не предоставляет `IFoo`, он реализует его:: - - >>> IFoo.providedBy(Foo) - False - -Мы можем также узнать какие интерфейсы реализуются объектами:: - - >>> list(zope.interface.implementedBy(Foo)) - [<InterfaceClass __main__.IFoo>] - -Это ошибка спрашивать про интерфейсы реализуемые невызываемым объектом:: - - >>> IFoo.implementedBy(foo) - Traceback (most recent call last): - ... - TypeError: ('ImplementedBy called for non-factory', Foo(None)) - - >>> list(zope.interface.implementedBy(foo)) - Traceback (most recent call last): - ... - TypeError: ('ImplementedBy called for non-factory', Foo(None)) - -Также можно узнать какие интерфейсы предоставляются объектами:: - - >>> list(zope.interface.providedBy(foo)) - [<InterfaceClass __main__.IFoo>] - >>> list(zope.interface.providedBy(Foo)) - [] - -Мы можем объявить интерфейсы реализуемые другими фабриками (кроме классов). -Это можно сделать используя декоратор `implementer` (в стиле Python 2.4). -Для версий Python ниже 2.4 это будет выглядеть следующим образом: - - >>> def yfoo(y): - ... foo = Foo() - ... foo.y = y - ... return foo - >>> yfoo = zope.interface.implementer(IFoo)(yfoo) - - >>> list(zope.interface.implementedBy(yfoo)) - [<InterfaceClass __main__.IFoo>] - -Надо заметить, что декоратор implementer может модифицировать свои аргументы. -Вызывающая сторона не должна предполагать, что всегда будет создаваться -новый объект. - -Также надо отметить, что как минимум сейчас implementer не может использоваться -для классов: - - >>> zope.interface.implementer(IFoo)(Foo) - ... # doctest: +NORMALIZE_WHITESPACE - Traceback (most recent call last): - ... - TypeError: Can't use implementer with classes. - Use one of the class-declaration functions instead. - -Объявление предоставляемых интерфейсов --------------------------------------- - -Мы можем объявлять интерфейсы напрямую предоставляемые объектами. Предположим -что мы хотим документировать что делает метод `__init__` класса `Foo`. Это -*точно* не часть `IFoo`. Обычно мы не должны напрямую вызывать метод `__init__` -для экземпляров Foo. Скорее метод `__init__` является частью метода `__call__` -класса `Foo`:: - - >>> class IFooFactory(zope.interface.Interface): - ... """Create foos""" - ... - ... def __call__(x=None): - ... """Create a foo - ... - ... The argument provides the initial value for x ... - ... """ - -У нас есть класс предоставляющий данный интерфейс, таким образом мы можем -объявить интерфейс класса:: - - >>> zope.interface.directlyProvides(Foo, IFooFactory) - -Теперь мы видим, что Foo уже предоставляет интерфейсы:: - - >>> list(zope.interface.providedBy(Foo)) - [<InterfaceClass __main__.IFooFactory>] - >>> IFooFactory.providedBy(Foo) - True - -Объявление интерфейсов класса достаточно частая операция и для нее есть -специальная функция объявления `classProvides`, которая позволяет объявлять -интерфейсы при определении класса:: - - >>> class Foo2: - ... zope.interface.implements(IFoo) - ... zope.interface.classProvides(IFooFactory) - ... - ... def __init__(self, x=None): - ... self.x = x - ... - ... def bar(self, q, r=None): - ... return q, r, self.x - ... - ... def __repr__(self): - ... return "Foo(%s)" % self.x - - >>> list(zope.interface.providedBy(Foo2)) - [<InterfaceClass __main__.IFooFactory>] - >>> IFooFactory.providedBy(Foo2) - True - -Похожая функция `moduleProvides` поддерживает объявление интерфейсов при -определении модуля. Для примера смотрите использование вызова -`moduleProvides` в `zope.interface.__init__`, который объявляет, что -пакет `zope.interface` предоставляет `IInterfaceDeclaration`. - -Иногда мы хотим объявить интерфейсы экземпляров, даже если эти экземпляры -уже берут интерфейсы от своих классов. Предположим, что мы создаем новый -интерфейс `ISpecial`:: - - >>> class ISpecial(zope.interface.Interface): - ... reason = zope.interface.Attribute("Reason why we're special") - ... def brag(): - ... "Brag about being special" - -Мы можем сделать созданный экземпляр foo специальным предоставив атрибуты -`reason` и `brag`:: - - >>> foo.reason = 'I just am' - >>> def brag(): - ... return "I'm special!" - >>> foo.brag = brag - >>> foo.reason - 'I just am' - >>> foo.brag() - "I'm special!" - -и объявив интерфейс:: - - >>> zope.interface.directlyProvides(foo, ISpecial) - -таким образом новый интерфейс включается в список предоставляемых интерфейсов:: - - >>> ISpecial.providedBy(foo) - True - >>> list(zope.interface.providedBy(foo)) - [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>] - -Мы также можем определить, что интерфейсы напрямую предоставляются -объектами:: - - >>> list(zope.interface.directlyProvidedBy(foo)) - [<InterfaceClass __main__.ISpecial>] - - >>> newfoo = Foo() - >>> list(zope.interface.directlyProvidedBy(newfoo)) - [] - -Наследуемые объявления ----------------------- - -Обычно объявления наследуются:: - - >>> class SpecialFoo(Foo): - ... zope.interface.implements(ISpecial) - ... reason = 'I just am' - ... def brag(self): - ... return "I'm special because %s" % self.reason - - >>> list(zope.interface.implementedBy(SpecialFoo)) - [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>] - - >>> list(zope.interface.providedBy(SpecialFoo())) - [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>] - -Иногда мы не хотим наследовать объявления. В этом случае мы можем -использовать `implementsOnly` вместо `implements`:: - - >>> class Special(Foo): - ... zope.interface.implementsOnly(ISpecial) - ... reason = 'I just am' - ... def brag(self): - ... return "I'm special because %s" % self.reason - - >>> list(zope.interface.implementedBy(Special)) - [<InterfaceClass __main__.ISpecial>] - - >>> list(zope.interface.providedBy(Special())) - [<InterfaceClass __main__.ISpecial>] - -Внешние объявления ------------------- - -Обычно мы создаем объявления реализации как часть объявления класса. Иногда -мы можем захотеть создать объявления вне объявления класса. Для примера, -мы можем хотеть объявить интерфейсы для классов которые писали не мы. -Для этого может использоваться функция `classImplements`:: - - >>> class C: - ... pass - - >>> zope.interface.classImplements(C, IFoo) - >>> list(zope.interface.implementedBy(C)) - [<InterfaceClass __main__.IFoo>] - -Мы можем использовать `classImplementsOnly` для исключения наследуемых -интерфейсов:: - - >>> class C(Foo): - ... pass - - >>> zope.interface.classImplementsOnly(C, ISpecial) - >>> list(zope.interface.implementedBy(C)) - [<InterfaceClass __main__.ISpecial>] - -Объекты объявлений ------------------- - -Когда мы объявляем интерфейсы мы создаем объект *объявления*. Когда мы -запрашиваем объявления возвращается объект объявления:: - - >>> type(zope.interface.implementedBy(Special)) - <class 'zope.interface.declarations.Implements'> - -Объекты объявления и объекты интерфейсов во многом похожи друг на друга. -На самом деле они даже имеют общий базовый класс. Важно понять, что они могут -использоваться там где в объявлениях ожидаются интерфейсы. Вот простой -пример:: - - >>> class Special2(Foo): - ... zope.interface.implementsOnly( - ... zope.interface.implementedBy(Foo), - ... ISpecial, - ... ) - ... reason = 'I just am' - ... def brag(self): - ... return "I'm special because %s" % self.reason - -Объявление здесь практически такое же как -``zope.interface.implements(ISpecial)``, отличие только в порядке -интерфейсов в итоговом объявления:: - - >>> list(zope.interface.implementedBy(Special2)) - [<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.ISpecial>] - -Наследование интерфейсов -======================== - -Интерфейсы могут расширять другие интерфейсы. Они делают это просто -показывая эти интерфейсы как базовые:: - - >>> class IBlat(zope.interface.Interface): - ... """Blat blah blah""" - ... - ... y = zope.interface.Attribute("y blah blah") - ... def eek(): - ... """eek blah blah""" - - >>> IBlat.__bases__ - (<InterfaceClass zope.interface.Interface>,) - - >>> class IBaz(IFoo, IBlat): - ... """Baz blah""" - ... def eek(a=1): - ... """eek in baz blah""" - ... - - >>> IBaz.__bases__ - (<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.IBlat>) - - >>> names = list(IBaz) - >>> names.sort() - >>> names - ['bar', 'eek', 'x', 'y'] - -Заметим, что `IBaz` переопределяет eek:: - - >>> IBlat['eek'].__doc__ - 'eek blah blah' - >>> IBaz['eek'].__doc__ - 'eek in baz blah' - -Мы были осторожны переопределяя eek совместимым путем. Когда интерфейс -расширяется, расширенный интерфейс должен быть совместимым [#compat]_ с -расширяемыми интерфейсами. - -Мы можем запросить расширяет ли один из интерфейсов другой:: - - >>> IBaz.extends(IFoo) - True - >>> IBlat.extends(IFoo) - False - -Заметим, что интерфейсы не расширяют сами себя:: - - >>> IBaz.extends(IBaz) - False - -Иногда мы можем хотеть что бы они расширяли сами себя, но вместо этого -мы можем использовать `isOrExtends`:: - - >>> IBaz.isOrExtends(IBaz) - True - >>> IBaz.isOrExtends(IFoo) - True - >>> IFoo.isOrExtends(IBaz) - False - -Когда мы применяем итерацию к интерфесу мы получаем все имена которые он -определяет включая имена определенные для базовых интерфесов. Иногда -мы хотим получить *только* имена определенные интерфейсом напрямую. -Для этого мы используем метод `names`:: - - >>> list(IBaz.names()) - ['eek'] - -Наследование в случае определения атрибутов --------------------------------------------- - -Интерфейс может переопределять определения атрибутов из базовых интерфейсов. -Если два базовых интерфейса определяют один и тот же атрибут атрибут -наследуется от более специфичного интерфейса. Для примера: - - >>> class IBase(zope.interface.Interface): - ... - ... def foo(): - ... "base foo doc" - - >>> class IBase1(IBase): - ... pass - - >>> class IBase2(IBase): - ... - ... def foo(): - ... "base2 foo doc" - - >>> class ISub(IBase1, IBase2): - ... pass - -Определение ISub для foo будет из IBase2 т.к. IBase2 более специфичен для -IBase: - - >>> ISub['foo'].__doc__ - 'base2 foo doc' - -Заметим, что это отличается от поиска в глубину. - -Иногда полезно узнать, что интерфейс определяет атрибут напрямую. Мы можем -использовать метод direct для получения напрямую определенных атрибутов: - - >>> IBase.direct('foo').__doc__ - 'base foo doc' - - >>> ISub.direct('foo') - -Спецификации ------------- - -Интерфейсы и объявления - это специальные случаи спецификаций. Описание -выше для наследования интерфейсов можно применить и к объявлениям и -к спецификациям. Объявления фактически расширяют интерфейсы которые они -объявляют: - - >>> class Baz: - ... zope.interface.implements(IBaz) - - >>> baz_implements = zope.interface.implementedBy(Baz) - >>> baz_implements.__bases__ - (<InterfaceClass __main__.IBaz>,) - - >>> baz_implements.extends(IFoo) - True - - >>> baz_implements.isOrExtends(IFoo) - True - >>> baz_implements.isOrExtends(baz_implements) - True - -Спецификации (интерфейсы и объявления) предоставляют атрибут `__sro__` -который описывает спецификацию и всех ее предков: - - >>> baz_implements.__sro__ - (<implementedBy __main__.Baz>, - <InterfaceClass __main__.IBaz>, - <InterfaceClass __main__.IFoo>, - <InterfaceClass __main__.IBlat>, - <InterfaceClass zope.interface.Interface>) - -Помеченные значения -=================== - -Интерфейсы и описания атрибутов поддерживают механизм расширения -заимствованный из UML и называемый "помеченные значения" который позволяет -сохранять дополнительные данные:: - - >>> IFoo.setTaggedValue('date-modified', '2004-04-01') - >>> IFoo.setTaggedValue('author', 'Jim Fulton') - >>> IFoo.getTaggedValue('date-modified') - '2004-04-01' - >>> IFoo.queryTaggedValue('date-modified') - '2004-04-01' - >>> IFoo.queryTaggedValue('datemodified') - >>> tags = list(IFoo.getTaggedValueTags()) - >>> tags.sort() - >>> tags - ['author', 'date-modified'] - -Атрибуты функций конвертируются в помеченные значения когда создаются -определения атрибутов метода:: - - >>> class IBazFactory(zope.interface.Interface): - ... def __call__(): - ... "create one" - ... __call__.return_type = IBaz - - >>> IBazFactory['__call__'].getTaggedValue('return_type') - <InterfaceClass __main__.IBaz> - -Инварианты -========== - -Интерфейсы могут описывать условия которые должны быть соблюдены для объектов -которые их предоставляют. Эти условия описываются используя один или более -инвариантов. Инварианты - это вызываемые объекты которые будут вызваны -с объектом предоставляющим интерфейс в качестве параметра. Инвариант -должен выкинуть исключение `Invalid` если условие не соблюдено. Например:: - - >>> class RangeError(zope.interface.Invalid): - ... """A range has invalid limits""" - ... def __repr__(self): - ... return "RangeError(%r)" % self.args - - >>> def range_invariant(ob): - ... if ob.max < ob.min: - ... raise RangeError(ob) - -Определив этот инвариант мы можем использовать его в определении интерфейсов:: - - >>> class IRange(zope.interface.Interface): - ... min = zope.interface.Attribute("Lower bound") - ... max = zope.interface.Attribute("Upper bound") - ... - ... zope.interface.invariant(range_invariant) - -Интерфейсы имеют метод для проверки своих инвариантов:: - - >>> class Range(object): - ... zope.interface.implements(IRange) - ... - ... def __init__(self, min, max): - ... self.min, self.max = min, max - ... - ... def __repr__(self): - ... return "Range(%s, %s)" % (self.min, self.max) - - >>> IRange.validateInvariants(Range(1,2)) - >>> IRange.validateInvariants(Range(1,1)) - >>> IRange.validateInvariants(Range(2,1)) - Traceback (most recent call last): - ... - RangeError: Range(2, 1) - -В случае нескольких инвариантов мы можем захотеть остановить проверку после -первой ошибки. Если мы передадим в `validateInvariants` пустой список тогда -будет выкинуто единственное исключение `Invalid` со списком исключений -как аргументом:: - - >>> errors = [] - >>> IRange.validateInvariants(Range(2,1), errors) - Traceback (most recent call last): - ... - Invalid: [RangeError(Range(2, 1))] - -И список будет заполнен индивидуальными исключениями:: - - >>> errors - [RangeError(Range(2, 1))] - - -.. [#create] Основная причина по которой мы наследуемся от `Interface` - это - что бы быть уверенными в том, что ключевое слово class будет - создавать интерфейс, а не класс. - - Есть возможность создать интерфейсы вызвав специальный - класс интерфейса напрямую. Делая это, возможно (и в редких - случаях полезно) создать интерфейсы которые не наследуются - от `Interface`. Однако использование этой техники выходит - за рамки данного документа. - -.. [#factory] Классы - это фабрики. Они могут быть вызваны для создания - своих экземпляров. Мы ожидаем что в итоге мы расширим - концепцию реализации на другие типы фабрик, таким образом - мы сможем объявлять интерфейсы предоставляемые созданными - фабриками объектами. - -.. [#compat] Цель - заменяемость. Объект который предоставляет расширенный - интерфейс должен быть заменяем в качестве объектов которые - предоставляют расширяемый интерфейс. В нашем примере объект - который предоставляет IBaz должен быть используемым и - в случае если ожидается объект который предоставляет IBlat. - - Реализация интерфейса не требует этого. Но возможно в дальнейшем - она должна будет делать какие-либо проверки. diff --git a/src/zope/interface/README.txt b/src/zope/interface/README.txt deleted file mode 100644 index 529ef00..0000000 --- a/src/zope/interface/README.txt +++ /dev/null @@ -1,699 +0,0 @@ -========== -Interfaces -========== - -.. contents:: - -Interfaces are objects that specify (document) the external behavior -of objects that "provide" them. An interface specifies behavior -through: - -- Informal documentation in a doc string - -- Attribute definitions - -- Invariants, which are conditions that must hold for objects that - provide the interface - -Attribute definitions specify specific attributes. They define the -attribute name and provide documentation and constraints of attribute -values. Attribute definitions can take a number of forms, as we'll -see below. - -Defining interfaces -=================== - -Interfaces are defined using Python class statements: - - >>> import zope.interface - >>> class IFoo(zope.interface.Interface): - ... """Foo blah blah""" - ... - ... x = zope.interface.Attribute("""X blah blah""") - ... - ... def bar(q, r=None): - ... """bar blah blah""" - -In the example above, we've created an interface, `IFoo`. We -subclassed `zope.interface.Interface`, which is an ancestor interface for -all interfaces, much as `object` is an ancestor of all new-style -classes [#create]_. The interface is not a class, it's an Interface, -an instance of `InterfaceClass`:: - - >>> type(IFoo) - <class 'zope.interface.interface.InterfaceClass'> - -We can ask for the interface's documentation:: - - >>> IFoo.__doc__ - 'Foo blah blah' - -and its name:: - - >>> IFoo.__name__ - 'IFoo' - -and even its module:: - - >>> IFoo.__module__ - '__main__' - -The interface defined two attributes: - -`x` - This is the simplest form of attribute definition. It has a name - and a doc string. It doesn't formally specify anything else. - -`bar` - This is a method. A method is defined via a function definition. A - method is simply an attribute constrained to be a callable with a - particular signature, as provided by the function definition. - - Note that `bar` doesn't take a `self` argument. Interfaces document - how an object is *used*. When calling instance methods, you don't - pass a `self` argument, so a `self` argument isn't included in the - interface signature. The `self` argument in instance methods is - really an implementation detail of Python instances. Other objects, - besides instances can provide interfaces and their methods might not - be instance methods. For example, modules can provide interfaces and - their methods are usually just functions. Even instances can have - methods that are not instance methods. - -You can access the attributes defined by an interface using mapping -syntax:: - - >>> x = IFoo['x'] - >>> type(x) - <class 'zope.interface.interface.Attribute'> - >>> x.__name__ - 'x' - >>> x.__doc__ - 'X blah blah' - - >>> IFoo.get('x').__name__ - 'x' - - >>> IFoo.get('y') - -You can use `in` to determine if an interface defines a name:: - - >>> 'x' in IFoo - True - -You can iterate over interfaces to get the names they define:: - - >>> names = list(IFoo) - >>> names.sort() - >>> names - ['bar', 'x'] - -Remember that interfaces aren't classes. You can't access attribute -definitions as attributes of interfaces:: - - >>> IFoo.x - Traceback (most recent call last): - File "<stdin>", line 1, in ? - AttributeError: 'InterfaceClass' object has no attribute 'x' - -Methods provide access to the method signature:: - - >>> bar = IFoo['bar'] - >>> bar.getSignatureString() - '(q, r=None)' - -TODO - Methods really should have a better API. This is something that - needs to be improved. - -Declaring interfaces -==================== - -Having defined interfaces, we can *declare* that objects provide -them. Before we describe the details, lets define some terms: - -*provide* - We say that objects *provide* interfaces. If an object provides an - interface, then the interface specifies the behavior of the - object. In other words, interfaces specify the behavior of the - objects that provide them. - -*implement* - We normally say that classes *implement* interfaces. If a class - implements an interface, then the instances of the class provide - the interface. Objects provide interfaces that their classes - implement [#factory]_. (Objects can provide interfaces directly, - in addition to what their classes implement.) - - It is important to note that classes don't usually provide the - interfaces that they implement. - - We can generalize this to factories. For any callable object we - can declare that it produces objects that provide some interfaces - by saying that the factory implements the interfaces. - -Now that we've defined these terms, we can talk about the API for -declaring interfaces. - -Declaring implemented interfaces --------------------------------- - -The most common way to declare interfaces is using the implements -function in a class statement:: - - >>> class Foo: - ... zope.interface.implements(IFoo) - ... - ... def __init__(self, x=None): - ... self.x = x - ... - ... def bar(self, q, r=None): - ... return q, r, self.x - ... - ... def __repr__(self): - ... return "Foo(%s)" % self.x - - -In this example, we declared that `Foo` implements `IFoo`. This means -that instances of `Foo` provide `IFoo`. Having made this declaration, -there are several ways we can introspect the declarations. First, we -can ask an interface whether it is implemented by a class:: - - >>> IFoo.implementedBy(Foo) - True - -And we can ask whether an interface is provided by an object:: - - >>> foo = Foo() - >>> IFoo.providedBy(foo) - True - -Of course, `Foo` doesn't provide `IFoo`, it implements it:: - - >>> IFoo.providedBy(Foo) - False - -We can also ask what interfaces are implemented by an object:: - - >>> list(zope.interface.implementedBy(Foo)) - [<InterfaceClass __main__.IFoo>] - -It's an error to ask for interfaces implemented by a non-callable -object:: - - >>> IFoo.implementedBy(foo) - Traceback (most recent call last): - ... - TypeError: ('ImplementedBy called for non-factory', Foo(None)) - - >>> list(zope.interface.implementedBy(foo)) - Traceback (most recent call last): - ... - TypeError: ('ImplementedBy called for non-factory', Foo(None)) - -Similarly, we can ask what interfaces are provided by an object:: - - >>> list(zope.interface.providedBy(foo)) - [<InterfaceClass __main__.IFoo>] - >>> list(zope.interface.providedBy(Foo)) - [] - -We can declare interfaces implemented by other factories (besides -classes). We do this using a Python-2.4-style decorator named -`implementer`. In versions of Python before 2.4, this looks like: - - - >>> def yfoo(y): - ... foo = Foo() - ... foo.y = y - ... return foo - >>> yfoo = zope.interface.implementer(IFoo)(yfoo) - - >>> list(zope.interface.implementedBy(yfoo)) - [<InterfaceClass __main__.IFoo>] - -Note that the implementer decorator may modify it's argument. Callers -should not assume that a new object is created. - -Also note that, at least for now, implementer can't be used with -classes: - - >>> zope.interface.implementer(IFoo)(Foo) - ... # doctest: +NORMALIZE_WHITESPACE - Traceback (most recent call last): - ... - TypeError: Can't use implementer with classes. - Use one of the class-declaration functions instead. - -Declaring provided interfaces ------------------------------ - -We can declare interfaces directly provided by objects. Suppose that -we want to document what the `__init__` method of the `Foo` class -does. It's not *really* part of `IFoo`. You wouldn't normally call -the `__init__` method on Foo instances. Rather, the `__init__` method -is part of the `Foo`'s `__call__` method:: - - >>> class IFooFactory(zope.interface.Interface): - ... """Create foos""" - ... - ... def __call__(x=None): - ... """Create a foo - ... - ... The argument provides the initial value for x ... - ... """ - -It's the class that provides this interface, so we declare the -interface on the class:: - - >>> zope.interface.directlyProvides(Foo, IFooFactory) - -And then, we'll see that Foo provides some interfaces:: - - >>> list(zope.interface.providedBy(Foo)) - [<InterfaceClass __main__.IFooFactory>] - >>> IFooFactory.providedBy(Foo) - True - -Declaring class interfaces is common enough that there's a special -declaration function for it, `classProvides`, that allows the -declaration from within a class statement:: - - >>> class Foo2: - ... zope.interface.implements(IFoo) - ... zope.interface.classProvides(IFooFactory) - ... - ... def __init__(self, x=None): - ... self.x = x - ... - ... def bar(self, q, r=None): - ... return q, r, self.x - ... - ... def __repr__(self): - ... return "Foo(%s)" % self.x - - >>> list(zope.interface.providedBy(Foo2)) - [<InterfaceClass __main__.IFooFactory>] - >>> IFooFactory.providedBy(Foo2) - True - -There's a similar function, `moduleProvides`, that supports interface -declarations from within module definitions. For example, see the use -of `moduleProvides` call in `zope.interface.__init__`, which declares that -the package `zope.interface` provides `IInterfaceDeclaration`. - -Sometimes, we want to declare interfaces on instances, even though -those instances get interfaces from their classes. Suppose we create -a new interface, `ISpecial`:: - - >>> class ISpecial(zope.interface.Interface): - ... reason = zope.interface.Attribute("Reason why we're special") - ... def brag(): - ... "Brag about being special" - -We can make an existing foo instance special by providing `reason` -and `brag` attributes:: - - >>> foo.reason = 'I just am' - >>> def brag(): - ... return "I'm special!" - >>> foo.brag = brag - >>> foo.reason - 'I just am' - >>> foo.brag() - "I'm special!" - -and by declaring the interface:: - - >>> zope.interface.directlyProvides(foo, ISpecial) - -then the new interface is included in the provided interfaces:: - - >>> ISpecial.providedBy(foo) - True - >>> list(zope.interface.providedBy(foo)) - [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>] - -We can find out what interfaces are directly provided by an object:: - - >>> list(zope.interface.directlyProvidedBy(foo)) - [<InterfaceClass __main__.ISpecial>] - - >>> newfoo = Foo() - >>> list(zope.interface.directlyProvidedBy(newfoo)) - [] - -Inherited declarations ----------------------- - -Normally, declarations are inherited:: - - >>> class SpecialFoo(Foo): - ... zope.interface.implements(ISpecial) - ... reason = 'I just am' - ... def brag(self): - ... return "I'm special because %s" % self.reason - - >>> list(zope.interface.implementedBy(SpecialFoo)) - [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>] - - >>> list(zope.interface.providedBy(SpecialFoo())) - [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>] - -Sometimes, you don't want to inherit declarations. In that case, you -can use `implementsOnly`, instead of `implements`:: - - >>> class Special(Foo): - ... zope.interface.implementsOnly(ISpecial) - ... reason = 'I just am' - ... def brag(self): - ... return "I'm special because %s" % self.reason - - >>> list(zope.interface.implementedBy(Special)) - [<InterfaceClass __main__.ISpecial>] - - >>> list(zope.interface.providedBy(Special())) - [<InterfaceClass __main__.ISpecial>] - -External declarations ---------------------- - -Normally, we make implementation declarations as part of a class -definition. Sometimes, we may want to make declarations from outside -the class definition. For example, we might want to declare interfaces -for classes that we didn't write. The function `classImplements` can -be used for this purpose:: - - >>> class C: - ... pass - - >>> zope.interface.classImplements(C, IFoo) - >>> list(zope.interface.implementedBy(C)) - [<InterfaceClass __main__.IFoo>] - -We can use `classImplementsOnly` to exclude inherited interfaces:: - - >>> class C(Foo): - ... pass - - >>> zope.interface.classImplementsOnly(C, ISpecial) - >>> list(zope.interface.implementedBy(C)) - [<InterfaceClass __main__.ISpecial>] - - - -Declaration Objects -------------------- - -When we declare interfaces, we create *declaration* objects. When we -query declarations, declaration objects are returned:: - - >>> type(zope.interface.implementedBy(Special)) - <class 'zope.interface.declarations.Implements'> - -Declaration objects and interface objects are similar in many ways. In -fact, they share a common base class. The important thing to realize -about them is that they can be used where interfaces are expected in -declarations. Here's a silly example:: - - >>> class Special2(Foo): - ... zope.interface.implementsOnly( - ... zope.interface.implementedBy(Foo), - ... ISpecial, - ... ) - ... reason = 'I just am' - ... def brag(self): - ... return "I'm special because %s" % self.reason - -The declaration here is almost the same as -``zope.interface.implements(ISpecial)``, except that the order of -interfaces in the resulting declaration is different:: - - >>> list(zope.interface.implementedBy(Special2)) - [<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.ISpecial>] - - -Interface Inheritance -===================== - -Interfaces can extend other interfaces. They do this simply by listing -the other interfaces as base interfaces:: - - >>> class IBlat(zope.interface.Interface): - ... """Blat blah blah""" - ... - ... y = zope.interface.Attribute("y blah blah") - ... def eek(): - ... """eek blah blah""" - - >>> IBlat.__bases__ - (<InterfaceClass zope.interface.Interface>,) - - >>> class IBaz(IFoo, IBlat): - ... """Baz blah""" - ... def eek(a=1): - ... """eek in baz blah""" - ... - - >>> IBaz.__bases__ - (<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.IBlat>) - - >>> names = list(IBaz) - >>> names.sort() - >>> names - ['bar', 'eek', 'x', 'y'] - -Note that `IBaz` overrides eek:: - - >>> IBlat['eek'].__doc__ - 'eek blah blah' - >>> IBaz['eek'].__doc__ - 'eek in baz blah' - -We were careful to override eek in a compatible way. When extending -an interface, the extending interface should be compatible [#compat]_ -with the extended interfaces. - -We can ask whether one interface extends another:: - - >>> IBaz.extends(IFoo) - True - >>> IBlat.extends(IFoo) - False - -Note that interfaces don't extend themselves:: - - >>> IBaz.extends(IBaz) - False - -Sometimes we wish they did, but we can, instead use `isOrExtends`:: - - >>> IBaz.isOrExtends(IBaz) - True - >>> IBaz.isOrExtends(IFoo) - True - >>> IFoo.isOrExtends(IBaz) - False - -When we iterate over an interface, we get all of the names it defines, -including names defined by base interfaces. Sometimes, we want *just* -the names defined by the interface directly. We bane use the `names` -method for that:: - - >>> list(IBaz.names()) - ['eek'] - -Inheritance of attribute specifications ---------------------------------------- - -An interface may override attribute definitions from base interfaces. -If two base interfaces define the same attribute, the attribute is -inherited from the most specific interface. For example, with: - - >>> class IBase(zope.interface.Interface): - ... - ... def foo(): - ... "base foo doc" - - >>> class IBase1(IBase): - ... pass - - >>> class IBase2(IBase): - ... - ... def foo(): - ... "base2 foo doc" - - >>> class ISub(IBase1, IBase2): - ... pass - -ISub's definition of foo is the one from IBase2, since IBase2 is more -specific that IBase: - - >>> ISub['foo'].__doc__ - 'base2 foo doc' - -Note that this differs from a depth-first search. - -Sometimes, it's useful to ask whether an interface defines an -attribute directly. You can use the direct method to get a directly -defined definitions: - - >>> IBase.direct('foo').__doc__ - 'base foo doc' - - >>> ISub.direct('foo') - -Specifications --------------- - -Interfaces and declarations are both special cases of specifications. -What we described above for interface inheritance applies to both -declarations and specifications. Declarations actually extend the -interfaces that they declare: - - >>> class Baz: - ... zope.interface.implements(IBaz) - - >>> baz_implements = zope.interface.implementedBy(Baz) - >>> baz_implements.__bases__ - (<InterfaceClass __main__.IBaz>,) - - >>> baz_implements.extends(IFoo) - True - - >>> baz_implements.isOrExtends(IFoo) - True - >>> baz_implements.isOrExtends(baz_implements) - True - -Specifications (interfaces and declarations) provide an `__sro__` -that lists the specification and all of it's ancestors: - - >>> baz_implements.__sro__ - (<implementedBy __main__.Baz>, - <InterfaceClass __main__.IBaz>, - <InterfaceClass __main__.IFoo>, - <InterfaceClass __main__.IBlat>, - <InterfaceClass zope.interface.Interface>) - - -Tagged Values -============= - -Interfaces and attribute descriptions support an extension mechanism, -borrowed from UML, called "tagged values" that lets us store extra -data:: - - >>> IFoo.setTaggedValue('date-modified', '2004-04-01') - >>> IFoo.setTaggedValue('author', 'Jim Fulton') - >>> IFoo.getTaggedValue('date-modified') - '2004-04-01' - >>> IFoo.queryTaggedValue('date-modified') - '2004-04-01' - >>> IFoo.queryTaggedValue('datemodified') - >>> tags = list(IFoo.getTaggedValueTags()) - >>> tags.sort() - >>> tags - ['author', 'date-modified'] - -Function attributes are converted to tagged values when method -attribute definitions are created:: - - >>> class IBazFactory(zope.interface.Interface): - ... def __call__(): - ... "create one" - ... __call__.return_type = IBaz - - >>> IBazFactory['__call__'].getTaggedValue('return_type') - <InterfaceClass __main__.IBaz> - - -Invariants -========== - -Interfaces can express conditions that must hold for objects that -provide them. These conditions are expressed using one or more -invariants. Invariants are callable objects that will be called with -an object that provides an interface. An invariant raises an `Invalid` -exception if the condition doesn't hold. Here's an example:: - - >>> class RangeError(zope.interface.Invalid): - ... """A range has invalid limits""" - ... def __repr__(self): - ... return "RangeError(%r)" % self.args - - >>> def range_invariant(ob): - ... if ob.max < ob.min: - ... raise RangeError(ob) - -Given this invariant, we can use it in an interface definition:: - - >>> class IRange(zope.interface.Interface): - ... min = zope.interface.Attribute("Lower bound") - ... max = zope.interface.Attribute("Upper bound") - ... - ... zope.interface.invariant(range_invariant) - -Interfaces have a method for checking their invariants:: - - >>> class Range(object): - ... zope.interface.implements(IRange) - ... - ... def __init__(self, min, max): - ... self.min, self.max = min, max - ... - ... def __repr__(self): - ... return "Range(%s, %s)" % (self.min, self.max) - - >>> IRange.validateInvariants(Range(1,2)) - >>> IRange.validateInvariants(Range(1,1)) - >>> IRange.validateInvariants(Range(2,1)) - Traceback (most recent call last): - ... - RangeError: Range(2, 1) - -If you have multiple invariants, you may not want to stop checking -after the first error. If you pass a list to `validateInvariants`, -then a single `Invalid` exception will be raised with the list of -exceptions as it's argument:: - - >>> errors = [] - >>> IRange.validateInvariants(Range(2,1), errors) - Traceback (most recent call last): - ... - Invalid: [RangeError(Range(2, 1))] - -And the list will be filled with the individual exceptions:: - - >>> errors - [RangeError(Range(2, 1))] - - - >>> del errors[:] - - - - -.. [#create] The main reason we subclass `Interface` is to cause the - Python class statement to create an interface, rather - than a class. - - It's possible to create interfaces by calling a special - interface class directly. Doing this, it's possible - (and, on rare occasions, useful) to create interfaces - that don't descend from `Interface`. Using this - technique is beyond the scope of this document. - -.. [#factory] Classes are factories. They can be called to create - their instances. We expect that we will eventually - extend the concept of implementation to other kinds of - factories, so that we can declare the interfaces - provided by the objects created. - -.. [#compat] The goal is substitutability. An object that provides an - extending interface should be substitutable for an object - that provides the extended interface. In our example, an - object that provides IBaz should be usable whereever an - object that provides IBlat is expected. - - The interface implementation doesn't enforce this. - but maybe it should do some checks. diff --git a/src/zope/interface/SETUP.cfg b/src/zope/interface/SETUP.cfg deleted file mode 100644 index db9a8f0..0000000 --- a/src/zope/interface/SETUP.cfg +++ /dev/null @@ -1,5 +0,0 @@ -# Extension information for zpkg: - -<extension _zope_interface_coptimizations> - source _zope_interface_coptimizations.c -</extension> diff --git a/src/zope/interface/__init__.py b/src/zope/interface/__init__.py deleted file mode 100644 index 50227f6..0000000 --- a/src/zope/interface/__init__.py +++ /dev/null @@ -1,80 +0,0 @@ -############################################################################## -# -# Copyright (c) 2001, 2002 Zope Corporation 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. -# -############################################################################## -"""Interfaces - -This package implements the Python "scarecrow" proposal. - -The package exports two objects, `Interface` and `Attribute` directly. It also -exports several helper methods. Interface is used to create an interface with -a class statement, as in: - - class IMyInterface(Interface): - '''Interface documentation - ''' - - def meth(arg1, arg2): - '''Documentation for meth - ''' - - # Note that there is no self argument - -To find out what you can do with interfaces, see the interface -interface, `IInterface` in the `interfaces` module. - -The package has several public modules: - - o `declarations` provides utilities to declare interfaces on objects. It - also provides a wide range of helpful utilities that aid in managing - declared interfaces. Most of its public names are however imported here. - - o `document` has a utility for documenting an interface as structured text. - - o `exceptions` has the interface-defined exceptions - - o `interfaces` contains a list of all public interfaces for this package. - - o `verify` has utilities for verifying implementations of interfaces. - -See the module doc strings for more information. - -$Id$ -""" -__docformat__ = 'restructuredtext' - -from zope.interface.interface import Interface, _wire - -# Need to actually get the interface elements to implement the right interfaces -_wire() -del _wire - -from zope.interface.interface import Attribute, invariant - -from zope.interface.declarations import providedBy, implementedBy -from zope.interface.declarations import classImplements, classImplementsOnly -from zope.interface.declarations import directlyProvidedBy, directlyProvides -from zope.interface.declarations import alsoProvides, implementer -from zope.interface.declarations import implements, implementsOnly -from zope.interface.declarations import classProvides, moduleProvides -from zope.interface.declarations import Declaration -from zope.interface.exceptions import Invalid - -# The following are to make spec pickles cleaner -from zope.interface.declarations import Provides - - -from zope.interface.interfaces import IInterfaceDeclaration - -moduleProvides(IInterfaceDeclaration) - -__all__ = ('Interface', 'Attribute') + tuple(IInterfaceDeclaration) diff --git a/src/zope/interface/_flatten.py b/src/zope/interface/_flatten.py deleted file mode 100644 index 7645abb..0000000 --- a/src/zope/interface/_flatten.py +++ /dev/null @@ -1,37 +0,0 @@ -############################################################################## -# -# Copyright (c) 2002 Zope Corporation 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. -# -############################################################################## -"""Adapter-style interface registry - -See Adapter class. - -$Id$ -""" -from zope.interface import Declaration - -def _flatten(implements, include_None=0): - - try: - r = implements.flattened() - except AttributeError: - if implements is None: - r=() - else: - r = Declaration(implements).flattened() - - if not include_None: - return r - - r = list(r) - r.append(None) - return r diff --git a/src/zope/interface/_zope_interface_coptimizations.c b/src/zope/interface/_zope_interface_coptimizations.c deleted file mode 100644 index 94f83f8..0000000 --- a/src/zope/interface/_zope_interface_coptimizations.c +++ /dev/null @@ -1,554 +0,0 @@ -/*########################################################################### - # - # Copyright (c) 2003 Zope Corporation 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. - # - ############################################################################*/ - -#include "Python.h" -#include "structmember.h" - -#define TYPE(O) ((PyTypeObject*)(O)) -#define OBJECT(O) ((PyObject*)(O)) -#define CLASSIC(O) ((PyClassObject*)(O)) - -static PyObject *str__dict__, *str__implemented__, *strextends; -static PyObject *BuiltinImplementationSpecifications, *str__provides__; -static PyObject *str__class__, *str__providedBy__, *strisOrExtends; -static PyObject *empty, *fallback, *str_implied, *str_cls, *str_implements; -static PyTypeObject *Implements; - -static int imported_declarations = 0; - -static int -import_declarations(void) -{ - PyObject *declarations, *i; - - declarations = PyImport_ImportModule("zope.interface.declarations"); - if (declarations == NULL) - return -1; - - BuiltinImplementationSpecifications = PyObject_GetAttrString( - declarations, "BuiltinImplementationSpecifications"); - if (BuiltinImplementationSpecifications == NULL) - return -1; - - empty = PyObject_GetAttrString(declarations, "_empty"); - if (empty == NULL) - return -1; - - fallback = PyObject_GetAttrString(declarations, "implementedByFallback"); - if (fallback == NULL) - return -1; - - - - i = PyObject_GetAttrString(declarations, "Implements"); - if (i == NULL) - return -1; - - if (! PyType_Check(i)) - { - PyErr_SetString(PyExc_TypeError, - "zope.declarations.Implements is not a type"); - return -1; - } - - Implements = (PyTypeObject *)i; - - Py_DECREF(declarations); - - imported_declarations = 1; - return 0; -} - -static PyTypeObject SpecType; /* Forward */ - -static PyObject * -implementedByFallback(PyObject *cls) -{ - if (imported_declarations == 0 && import_declarations() < 0) - return NULL; - - return PyObject_CallFunctionObjArgs(fallback, cls, NULL); -} - -static PyObject * -implementedBy(PyObject *ignored, PyObject *cls) -{ - /* Fast retrieval of implements spec, if possible, to optimize - common case. Use fallback code if we get stuck. - */ - - PyObject *dict = NULL, *spec; - - if (PyType_Check(cls)) - { - dict = TYPE(cls)->tp_dict; - Py_XINCREF(dict); - } - - if (dict == NULL) - dict = PyObject_GetAttr(cls, str__dict__); - - if (dict == NULL) - { - /* Probably a security proxied class, use more expensive fallback code */ - PyErr_Clear(); - return implementedByFallback(cls); - } - - spec = PyObject_GetItem(dict, str__implemented__); - Py_DECREF(dict); - if (spec) - { - if (imported_declarations == 0 && import_declarations() < 0) - return NULL; - - if (PyObject_TypeCheck(spec, Implements)) - return spec; - - /* Old-style declaration, use more expensive fallback code */ - Py_DECREF(spec); - return implementedByFallback(cls); - } - - PyErr_Clear(); - - /* Maybe we have a builtin */ - if (imported_declarations == 0 && import_declarations() < 0) - return NULL; - - spec = PyDict_GetItem(BuiltinImplementationSpecifications, cls); - if (spec != NULL) - { - Py_INCREF(spec); - return spec; - } - - /* We're stuck, use fallback */ - return implementedByFallback(cls); -} - -static PyObject * -getObjectSpecification(PyObject *ignored, PyObject *ob) -{ - PyObject *cls, *result; - - result = PyObject_GetAttr(ob, str__provides__); - if (result != NULL) - return result; - - PyErr_Clear(); - - /* We do a getattr here so as not to be defeated by proxies */ - cls = PyObject_GetAttr(ob, str__class__); - if (cls == NULL) - { - PyErr_Clear(); - if (imported_declarations == 0 && import_declarations() < 0) - return NULL; - Py_INCREF(empty); - return empty; - } - - result = implementedBy(NULL, cls); - Py_DECREF(cls); - - return result; -} - -static PyObject * -providedBy(PyObject *ignored, PyObject *ob) -{ - PyObject *result, *cls, *cp; - - result = PyObject_GetAttr(ob, str__providedBy__); - if (result == NULL) - { - PyErr_Clear(); - return getObjectSpecification(NULL, ob); - } - - - /* We want to make sure we have a spec. We can't do a type check - because we may have a proxy, so we'll just try to get the - only attribute. - */ - if (PyObject_HasAttr(result, strextends)) - return result; - - /* - The object's class doesn't understand descriptors. - Sigh. We need to get an object descriptor, but we have to be - careful. We want to use the instance's __provides__,l if - there is one, but only if it didn't come from the class. - */ - Py_DECREF(result); - - cls = PyObject_GetAttr(ob, str__class__); - if (cls == NULL) - return NULL; - - result = PyObject_GetAttr(ob, str__provides__); - if (result == NULL) - { - /* No __provides__, so just fall back to implementedBy */ - PyErr_Clear(); - result = implementedBy(NULL, cls); - Py_DECREF(cls); - return result; - } - - cp = PyObject_GetAttr(cls, str__provides__); - if (cp == NULL) - { - /* The the class has no provides, assume we're done: */ - PyErr_Clear(); - Py_DECREF(cls); - return result; - } - - if (cp == result) - { - /* - Oops, we got the provides from the class. This means - the object doesn't have it's own. We should use implementedBy - */ - Py_DECREF(result); - result = implementedBy(NULL, cls); - } - - Py_DECREF(cls); - Py_DECREF(cp); - - return result; -} - -static PyObject * -inst_attr(PyObject *self, PyObject *name) -{ - /* Get an attribute from an inst dict. Return a borrowed reference. - */ - - PyObject **dictp, *v; - - dictp = _PyObject_GetDictPtr(self); - if (dictp && *dictp && (v = PyDict_GetItem(*dictp, name))) - return v; - PyErr_SetObject(PyExc_AttributeError, name); - return NULL; -} - - -static PyObject * -Spec_extends(PyObject *self, PyObject *other) -{ - PyObject *implied; - - implied = inst_attr(self, str_implied); - if (implied == NULL) - return NULL; - -#ifdef Py_True - if (PyDict_GetItem(implied, other) != NULL) - { - Py_INCREF(Py_True); - return Py_True; - } - Py_INCREF(Py_False); - return Py_False; -#else - return PyInt_FromLong(PyDict_GetItem(implied, other) != NULL); -#endif -} - -static char Spec_extends__doc__[] = -"Test whether a specification is or extends another" -; - -static char Spec_providedBy__doc__[] = -"Test whether an interface is implemented by the specification" -; - -static PyObject * -Spec_providedBy(PyObject *self, PyObject *ob) -{ - PyObject *decl, *item; - - decl = providedBy(NULL, ob); - if (decl == NULL) - return NULL; - - if (PyObject_TypeCheck(ob, &SpecType)) - item = Spec_extends(decl, self); - else - /* decl is probably a security proxy. We have to go the long way - around. - */ - item = PyObject_CallMethodObjArgs(decl, strisOrExtends, self, NULL); - - Py_DECREF(decl); - return item; -} - - -static char Spec_implementedBy__doc__[] = -"Test whether the specification is implemented by a class or factory.\n" -"Raise TypeError if argument is neither a class nor a callable." -; - -static PyObject * -Spec_implementedBy(PyObject *self, PyObject *cls) -{ - PyObject *decl, *item; - - decl = implementedBy(NULL, cls); - if (decl == NULL) - return NULL; - - if (PyObject_TypeCheck(decl, &SpecType)) - item = Spec_extends(decl, self); - else - item = PyObject_CallMethodObjArgs(decl, strisOrExtends, self, NULL); - - Py_DECREF(decl); - return item; -} - -static struct PyMethodDef Spec_methods[] = { - {"providedBy", - (PyCFunction)Spec_providedBy, METH_O, - Spec_providedBy__doc__}, - {"implementedBy", - (PyCFunction)Spec_implementedBy, METH_O, - Spec_implementedBy__doc__}, - {"isOrExtends", (PyCFunction)Spec_extends, METH_O, - Spec_extends__doc__}, - - {NULL, NULL} /* sentinel */ -}; - -static PyTypeObject SpecType = { - PyObject_HEAD_INIT(NULL) - /* ob_size */ 0, - /* tp_name */ "_interface_coptimizations." - "SpecificationBase", - /* tp_basicsize */ 0, - /* tp_itemsize */ 0, - /* tp_dealloc */ (destructor)0, - /* tp_print */ (printfunc)0, - /* tp_getattr */ (getattrfunc)0, - /* tp_setattr */ (setattrfunc)0, - /* tp_compare */ (cmpfunc)0, - /* tp_repr */ (reprfunc)0, - /* tp_as_number */ 0, - /* tp_as_sequence */ 0, - /* tp_as_mapping */ 0, - /* tp_hash */ (hashfunc)0, - /* tp_call */ (ternaryfunc)0, - /* tp_str */ (reprfunc)0, - /* tp_getattro */ (getattrofunc)0, - /* tp_setattro */ (setattrofunc)0, - /* tp_as_buffer */ 0, - /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - "Base type for Specification objects", - /* tp_traverse */ (traverseproc)0, - /* tp_clear */ (inquiry)0, - /* tp_richcompare */ (richcmpfunc)0, - /* tp_weaklistoffset */ (long)0, - /* tp_iter */ (getiterfunc)0, - /* tp_iternext */ (iternextfunc)0, - /* tp_methods */ Spec_methods, -}; - -static PyObject * -OSD_descr_get(PyObject *self, PyObject *inst, PyObject *cls) -{ - PyObject *provides; - - if (inst == NULL) - return getObjectSpecification(NULL, cls); - - provides = PyObject_GetAttr(inst, str__provides__); - if (provides != NULL) - return provides; - PyErr_Clear(); - return implementedBy(NULL, cls); -} - -static PyTypeObject OSDType = { - PyObject_HEAD_INIT(NULL) - /* ob_size */ 0, - /* tp_name */ "_interface_coptimizations." - "ObjectSpecificationDescriptor", - /* tp_basicsize */ 0, - /* tp_itemsize */ 0, - /* tp_dealloc */ (destructor)0, - /* tp_print */ (printfunc)0, - /* tp_getattr */ (getattrfunc)0, - /* tp_setattr */ (setattrfunc)0, - /* tp_compare */ (cmpfunc)0, - /* tp_repr */ (reprfunc)0, - /* tp_as_number */ 0, - /* tp_as_sequence */ 0, - /* tp_as_mapping */ 0, - /* tp_hash */ (hashfunc)0, - /* tp_call */ (ternaryfunc)0, - /* tp_str */ (reprfunc)0, - /* tp_getattro */ (getattrofunc)0, - /* tp_setattro */ (setattrofunc)0, - /* tp_as_buffer */ 0, - /* tp_flags */ Py_TPFLAGS_DEFAULT - | Py_TPFLAGS_BASETYPE , - "Object Specification Descriptor", - /* tp_traverse */ (traverseproc)0, - /* tp_clear */ (inquiry)0, - /* tp_richcompare */ (richcmpfunc)0, - /* tp_weaklistoffset */ (long)0, - /* tp_iter */ (getiterfunc)0, - /* tp_iternext */ (iternextfunc)0, - /* tp_methods */ 0, - /* tp_members */ 0, - /* tp_getset */ 0, - /* tp_base */ 0, - /* tp_dict */ 0, /* internal use */ - /* tp_descr_get */ (descrgetfunc)OSD_descr_get, -}; - -static PyObject * -CPB_descr_get(PyObject *self, PyObject *inst, PyObject *cls) -{ - PyObject *mycls, *implements; - - mycls = inst_attr(self, str_cls); - if (mycls == NULL) - return NULL; - - if (cls == mycls) - { - if (inst == NULL) - { - Py_INCREF(self); - return OBJECT(self); - } - - implements = inst_attr(self, str_implements); - Py_XINCREF(implements); - return implements; - } - - PyErr_SetObject(PyExc_AttributeError, str__provides__); - return NULL; -} - -static PyTypeObject CPBType = { - PyObject_HEAD_INIT(NULL) - /* ob_size */ 0, - /* tp_name */ "_interface_coptimizations." - "ClassProvidesBase", - /* tp_basicsize */ 0, - /* tp_itemsize */ 0, - /* tp_dealloc */ (destructor)0, - /* tp_print */ (printfunc)0, - /* tp_getattr */ (getattrfunc)0, - /* tp_setattr */ (setattrfunc)0, - /* tp_compare */ (cmpfunc)0, - /* tp_repr */ (reprfunc)0, - /* tp_as_number */ 0, - /* tp_as_sequence */ 0, - /* tp_as_mapping */ 0, - /* tp_hash */ (hashfunc)0, - /* tp_call */ (ternaryfunc)0, - /* tp_str */ (reprfunc)0, - /* tp_getattro */ (getattrofunc)0, - /* tp_setattro */ (setattrofunc)0, - /* tp_as_buffer */ 0, - /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - "C Base class for ClassProvides", - /* tp_traverse */ (traverseproc)0, - /* tp_clear */ (inquiry)0, - /* tp_richcompare */ (richcmpfunc)0, - /* tp_weaklistoffset */ (long)0, - /* tp_iter */ (getiterfunc)0, - /* tp_iternext */ (iternextfunc)0, - /* tp_methods */ 0, - /* tp_members */ 0, - /* tp_getset */ 0, - /* tp_base */ &SpecType, - /* tp_dict */ 0, /* internal use */ - /* tp_descr_get */ (descrgetfunc)CPB_descr_get, -}; - - -static struct PyMethodDef m_methods[] = { - {"implementedBy", (PyCFunction)implementedBy, METH_O, - "Interfaces implemented by a class or factory.\n" - "Raises TypeError if argument is neither a class nor a callable."}, - {"getObjectSpecification", (PyCFunction)getObjectSpecification, METH_O, - "Get an object's interfaces (internal api)"}, - {"providedBy", (PyCFunction)providedBy, METH_O, - "Get an object's interfaces"}, - - {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */ -}; - -#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ -#define PyMODINIT_FUNC void -#endif -PyMODINIT_FUNC -init_zope_interface_coptimizations(void) -{ - PyObject *m; - -#define DEFINE_STRING(S) \ - if(! (str ## S = PyString_FromString(# S))) return - - DEFINE_STRING(__dict__); - DEFINE_STRING(__implemented__); - DEFINE_STRING(__provides__); - DEFINE_STRING(__class__); - DEFINE_STRING(__providedBy__); - DEFINE_STRING(isOrExtends); - DEFINE_STRING(extends); - DEFINE_STRING(_implied); - DEFINE_STRING(_implements); - DEFINE_STRING(_cls); -#undef DEFINE_STRING - - - /* Initialize types: */ - SpecType.tp_new = PyBaseObject_Type.tp_new; - if (PyType_Ready(&SpecType) < 0) - return; - OSDType.tp_new = PyBaseObject_Type.tp_new; - if (PyType_Ready(&OSDType) < 0) - return; - CPBType.tp_new = PyBaseObject_Type.tp_new; - if (PyType_Ready(&CPBType) < 0) - return; - - /* Create the module and add the functions */ - m = Py_InitModule3("_zope_interface_coptimizations", m_methods, - "C optimizations for zope.interface\n\n" - "$Id$"); - if (m == NULL) - return; - - /* Add types: */ - if (PyModule_AddObject(m, "SpecificationBase", (PyObject *)&SpecType) < 0) - return; - if (PyModule_AddObject(m, "ObjectSpecificationDescriptor", - (PyObject *)&OSDType) < 0) - return; - if (PyModule_AddObject(m, "ClassProvidesBase", (PyObject *)&CPBType) < 0) - return; -} diff --git a/src/zope/interface/adapter.py b/src/zope/interface/adapter.py deleted file mode 100644 index 45d760c..0000000 --- a/src/zope/interface/adapter.py +++ /dev/null @@ -1,744 +0,0 @@ -############################################################################ -# -# Copyright (c) 2002 Zope Corporation 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. -# -############################################################################ -"""Adapter-style interface registry - -This implementation is based on a notion of "surrogate" interfaces. - -$Id$ -""" - -# Implementation notes - -# We keep a collection of surrogates. - -# A surrogate is a surrogate for a specification (interface or -# declaration). We use weak references in order to remove surrogates -# if the corresponding specification goes away. - -# Each surrogate keeps track of: - -# - The adapters registered directly for that surrogate, and - -# - The "implied" adapters, which is the adapters that can be computed -# from instances of that surrogate. - -# The later data structure takes into account adapters registered for -# specifications that the registered surrogate extends. - -# The registrations are of the form: - -# {(subscription, with, name, specification) -> factories} - -# where: - -# 'subscription' is a flag indicating if this registration is for -# subscription adapters. - -# 'with' is a tuple of specs that is non-empty only in the case -# of multi-adapters. - -# 'name' is a unicode adapter name. Unnamed adapters have an empty -# name. - -# 'specification' is the interface being adapted to, the provided interface. - -# 'factories' is normally a tuple of factories, but can be anything. -# (See the "raw" option to the query-adapter calls.) For subscription -# adapters, it is a tuple of tuples of factories. - -# The implied adapters are held in a single dictionary. The items in the -# dictionary are of several forms: - -# For single adapters: -# -# {specification -> {name -> object} -# -# where object is usually a sequence of factories - -# For multiple adapters: -# -# {(specification, order) -> {name -> {with -> object}}} - -# For single subscription adapters: -# -# {('s', specification) -> tuple([object])} - -# For multiple-subscription adapters: -# -# {('s', specification, order) -> {with -> tuple([object])}} - - -from __future__ import generators - -import weakref -from zope.interface.ro import ro -from zope.interface.declarations import providedBy -from zope.interface.interface import InterfaceClass, Interface - -Default = InterfaceClass("Default", (), {}) -Null = InterfaceClass("Null", (), {}) - -# 2.2 backwards compatability -try: - enumerate -except NameError: - def enumerate(l): - i = 0 - for o in l: - yield i, o - i += 1 -try: - basestring -except NameError: - basestring = (str, unicode) - - -class ReadProperty(object): - - def __init__(self, func): - self.func = func - - def __get__(self, inst, class_): - if inst is None: - return self - return self.func(inst) - -class Surrogate(object): - """Specification surrogate - - A specification surrogate is used to hold adapter registrations on - behalf of a specification. - """ - - def __init__(self, spec, registry): - self.spec = spec.weakref() - self.registry = registry - spec.subscribe(self) - self.adapters = {} - self.dependents = weakref.WeakKeyDictionary() - - self.registry = registry - self.__bases__ = [registry.get(base) for base in spec.__bases__] - for base in self.__bases__: - base.subscribe(self) - - def dirty(self): - if 'get' in self.__dict__: - # Not already dirty - del self.selfImplied - del self.multImplied - del self.get - - bases = [self.registry.get(base) for base in self.spec().__bases__] - if bases != self.__bases__: - # Our bases changed. unsubscribe from the old ones - # and subscribe to the new ones - for base in self.__bases__: - base.unsubscribe(self) - - self.__bases__ = bases - for base in bases: - base.subscribe(self) - - for dependent in self.dependents.keys(): - dependent.dirty() - - def clean(self): - for base in self.__bases__: - base.unsubscribe(self) - self.__bases__ = [self.registry.get(base) - for base in self.spec().__bases__] - for base in self.__bases__: - base.subscribe(self) - - self.selfImplied, self.multImplied = adapterImplied(self.adapters) - - implied = {} - - ancestors = ro(self) - - # Collect implied data in reverse order to have more specific data - # override less-specific data. - ancestors.reverse() - for ancestor in ancestors: - ancestor_spec = ancestor.spec() - - for key, v in ancestor.selfImplied.iteritems(): - - # key is specification or ('s', specification) - subscription = isinstance(key, tuple) and key[0] == 's' - if subscription: - # v is tuple of subs - implied[key] = implied.get(key, ()) + v - else: - oldbyname = implied.get(key) - if not oldbyname: - implied[key] = oldbyname = {} - - # v is name -> object - oldbyname.update(v) - - for key, v in ancestor.multImplied.iteritems(): - # key is (specification, order) - # or ('s', specification, order) - subscription = key[0] == 's' - if subscription: - oldwithobs = implied.get(key) - if not oldwithobs: - oldwithobs = implied[key] = {} - - # v is {with -> tuple([object])} - for with, objects in v.iteritems(): - oldwithobs[with] = oldwithobs.get(with, ()) + objects - - else: - oldbyname = implied.get(key) - if not oldbyname: - implied[key] = oldbyname = {} - - - # v is {name -> {with -> ?}} - for name, withobs in v.iteritems(): - - # withobs is {with -> value} - - # If ancestor is not the default, - # add in ancestor so we can get ordering right - if ancestor_spec is not Default: - withobs = dict([ - (((ancestor_spec,) + with), value) - for (with, value) in withobs.iteritems() - ]) - - oldwithobs = oldbyname.get(name) - if not oldwithobs: - oldwithobs = oldbyname[name] = {} - - # withobs is {with -> object} - oldwithobs.update(withobs) - - # Now flatten with mappings to tuples - for key, v in implied.iteritems(): - if isinstance(key, tuple): - if key[0] == 's': - # subscriptions - if isinstance(v, dict): - implied[key] = v.items() - else: - byname = v - for name, value in byname.iteritems(): - if isinstance(value, dict): - # We have {with -> value} - # convert it to [(with, value] - byname[name] = value.items() - - self.get = implied.get - - def get(self, key): - """Get an implied value - - This is only called when the surrogate is dirty - """ - self.clean() - return self.__dict__['get'](key) - - def selfImplied(self): - """Return selfImplied when dirty - """ - self.clean() - return self.__dict__['selfImplied'] - selfImplied = ReadProperty(selfImplied) - - def multiImplied(self): - """Return _multiImplied when dirty - """ - self.clean() - return self.__dict__['multiImplied'] - multiImplied = ReadProperty(multiImplied) - - def subscribe(self, dependent): - self.dependents[dependent] = self.dependents.get(dependent, 0) + 1 - - def unsubscribe(self, dependent): - n = self.dependents.get(dependent, 0) - 1 - if not n: - del self.dependents[dependent] - elif n > 0: - self.dependents[dependent] = n - else: - raise KeyError(dependent) - - def _adaptTo(self, specification, object, name='', with=()): - if object is None: - try: - del self.adapters[False, tuple(with), name, specification] - except KeyError: - pass - else: - self.adapters[False, tuple(with), name, specification - ] = object - - self.dirty() - - def _subscriptionAdaptTo(self, specification, object, with=()): - if object is None: - raise TypeError("Unregistering subscription adapters isn't " - "implemented") - - key = (True, tuple(with), '', specification) - self.adapters[key] = self.adapters.get(key, ()) + (object, ) - self.dirty() - - def changed(self, which=None): - self.dirty() - - def __repr__(self): - return '<%s(%s)>' % (self.__class__.__name__, self.spec()) - - -class AdapterLookup(object): - # Adapter lookup support - # We have a class here because we want to provide very - # fast lookup support in C and making this part of the adapter - # registry itself would provide problems if someone wanted - # persistent adapter registries, because we want C slots for fast - # lookup that would clash with persistence-supplied slots. - # so this class acts a little bit like a lookup adapter for the adapter - # registry. - - def __init__(self, registry, surrogates, _remove): - self._registry = registry - self._surrogateClass = registry._surrogateClass - self._default = registry._default - self._null = registry._null - self._surrogates = surrogates - self._remove = _remove - - def lookup(self, required, provided, name='', default=None): - order = len(required) - if order == 1: - # Simple adapter: - s = self.get(required[0]) - byname = s.get(provided) - if byname: - value = byname.get(name) - else: - value = None - - if value is None: - byname = self._default.get(provided) - if byname: - value = byname.get(name, default) - else: - return default - - return value - - elif order == 0: - # null adapter - byname = self._null.get(provided) - if byname: - return byname.get(name, default) - else: - return default - - # Multi adapter - - with = required - key = provided, order - - for surrogate in self.get(required[0]), self._default: - byname = surrogate.get(key) - if byname: - bywith = byname.get(name) - if bywith: - # Selecting multi-adapters is not just a matter of - # matching the required interfaces of the adapter - # to the ones passed. Several adapters might - # match, but we only want the best one. We use a - # ranking algorithm to determine the best match. - # `best` carries the rank and value of the best - # found adapter. - best = None - for rwith, value in bywith: - # the `rank` describes how well the found - # adapter matches. - rank = [] - for rspec, spec in zip(rwith, with): - if not spec.isOrExtends(rspec): - break # This one is no good - - # Determine the rank of this particular - # specification. - rank.append(list(spec.__sro__).index(rspec)) - else: - # If the new rank is better than the best - # previously recorded one, make the new - # adapter the best one found. - rank = tuple(rank) - if best is None or rank < best[0]: - best = rank, value - # If any match was found, return the best one. - if best: - return best[1] - - with = with[1:] # on second pass through, don't use first spec - - return default - - def lookup1(self, required, provided, name='', default=None): - return self.lookup((required,), provided, name, default) - - def adapter_hook(self, interface, object, name='', default=None): - """Hook function used when calling interfaces. - - When called from Interface.__adapt__, only the interface and - object parameters will be passed. - - If the factory produces `None`, then the default is returned. This - allows us to prevent adaptation (if desired) and make the factory - decide whether an adapter will be available. - """ - factory = self.lookup1(providedBy(object), interface, name) - if factory is not None: - adapter = factory(object) - if adapter is not None: - return adapter - return default - - def queryAdapter(self, object, interface, name='', default=None): - # Note that we rarely call queryAdapter directly - # We usually end up calling adapter_hook - return self.adapter_hook(interface, object, name, default) - - def subscriptions(self, required, provided): - if provided is None: - provided = Null - - order = len(required) - if order == 1: - # Simple subscriptions: - s = self.get(required[0]) - result = s.get(('s', provided)) - if result: - result = list(result) - else: - result = [] - - default = self._default.get(('s', provided)) - if default: - result.extend(default) - - return result - - elif order == 0: - result = self._null.get(('s', provided)) - if result: - return list(result) - else: - return [] - - # Multi - key = 's', provided, order - with = required[1:] - result = [] - - for surrogate in self.get(required[0]), self._default: - bywith = surrogate.get(key) - if not bywith: - continue - - for rwith, values in bywith: - for rspec, spec in zip(rwith, with): - if not spec.isOrExtends(rspec): - break # This one is no good - else: - # we didn't break, so we have a match - result.extend(values) - - return result - - def queryMultiAdapter(self, objects, interface, name='', default=None): - factory = self.lookup(map(providedBy, objects), interface, name) - if factory is not None: - return factory(*objects) - - return default - - def subscribers(self, objects, interface): - subscriptions = self.subscriptions(map(providedBy, objects), interface) - subscribers = [subscription(*objects) - for subscription in subscriptions] - # Filter None values - return [x for x in subscribers if x is not None] - - def get(self, declaration): - if declaration is None: - return self._default - - ref = declaration.weakref(self._remove) - surrogate = self._surrogates.get(ref) - if surrogate is None: - surrogate = self._surrogateClass(declaration, self._registry) - self._surrogates[ref] = surrogate - - return surrogate - - -class AdapterRegistry(object): - """Adapter registry - """ - - # Implementation note: - # We are like a weakref dict ourselves. We can't use a weakref - # dict because we have to use spec.weakref() rather than - # weakref.ref(spec) to get weak refs to specs. - - _surrogateClass = Surrogate - - def __init__(self): - default = self._surrogateClass(Default, self) - self._default = default - null = self._surrogateClass(Null, self) - self._null = null - - # Create separate lookup object and copy it's methods - surrogates = {Default.weakref(): default, Null.weakref(): null} - def _remove(k): - try: - del surrogates[k] - except KeyError: - pass - lookup = AdapterLookup(self, surrogates, _remove) - - for name in ('lookup', 'lookup1', 'queryAdapter', 'get', - 'adapter_hook', 'subscriptions', - 'queryMultiAdapter', 'subscribers', - ): - setattr(self, name, getattr(lookup, name)) - - def register(self, required, provided, name, value): - if required: - with = [] - for iface in required[1:]: - if iface is None: - iface = Interface - with.append(iface) - with = tuple(with) - required = self.get(required[0]) - else: - with = () - required = self._null - - if not isinstance(name, basestring): - raise TypeError("The name provided to provideAdapter " - "must be a string or unicode") - - required._adaptTo(provided, value, unicode(name), with) - - def lookupAll(self, required, provided): - order = len(required) - if order == 1: - # Simple adapter: - s = self.get(required[0]) - byname = s.get(provided) - if byname: - for item in byname.iteritems(): - yield item - - defbyname = self._default.get(provided) - if defbyname: - for name, value in defbyname.iteritems(): - if name in byname: - continue - yield name, value - - return - - elif order == 0: - # null adapter - byname = self._null.get(provided) - if byname: - for item in byname.iteritems(): - yield item - - return - - - # Multi adapter - - with = required - key = provided, order - first = () - - for surrogate in self.get(required[0]), self._default: - byname = surrogate.get(key) - if byname: - for name, bywith in byname.iteritems(): - if not bywith or name in first: - continue - - # See comments on lookup() above - best = None - for rwith, value in bywith: - # the `rank` describes how well the found - # adapter matches. - rank = [] - for rspec, spec in zip(rwith, with): - if not spec.isOrExtends(rspec): - break # This one is no good - - # Determine the rank of this particular - # specification. - rank.append(list(spec.__sro__).index(rspec)) - else: - # If the new rank is better than the best - # previously recorded one, make the new - # adapter the best one found. - rank = tuple(rank) - if best is None or rank < best[0]: - best = rank, value - - # If any match was found, return the best one. - if best: - yield name, best[1] - - first = byname - - with = with[1:] # on second pass through, don't use first spec - - def subscribe(self, required, provided, value): - if required: - required, with = self.get(required[0]), tuple(required[1:]) - else: - required = self._null - with = () - - if provided is None: - provided = Null - - required._subscriptionAdaptTo(provided, value, with) - -def mextends(with, rwith): - if len(with) == len(rwith): - for w, r in zip(with, rwith): - if not w.isOrExtends(r): - break - else: - return True - return False - -def adapterImplied(adapters): - implied = {} - multi = {} - - # This dictionary is used to catch situations specific adapters - # override less specific adapters. - # Because subscriptions are cumulative, registered doesn't apply. - registered = {} - - # Add adapters and interfaces directly implied by same: - - for key, value in adapters.iteritems(): - - # TODO: Backward compatibility - # BBB ? Don't need to handle 3-tuples some day - try: - (subscription, with, name, target) = key - except ValueError: - (with, name, target) = key - subscription = False - - if subscription: - if with: - _add_multi_sub_adapter(with, target, multi, value) - else: - _add_named_sub_adapter(target, implied, value) - else: - if with: - _add_multi_adapter(with, name, target, target, multi, - registered, value) - else: - _add_named_adapter(target, target, name, implied, - registered, value) - - return implied, multi - -def _add_named_adapter(target, provided, name, implied, - registered, value): - - ikey = target - rkey = target, name - - byname = implied.get(ikey) - if not byname: - byname = implied[ikey] = {} - - if (name not in byname - or - (rkey in registered and registered[rkey].extends(provided)) - ): - - registered[rkey] = provided - byname[name] = value - - for b in target.__bases__: - _add_named_adapter(b, provided, name, implied, - registered, value) - -def _add_multi_adapter(with, name, target, provided, implied, - registered, object): - - ikey = target, (len(with) + 1) - byname = implied.get(ikey) - if not byname: - byname = implied[ikey] = {} - - bywith = byname.get(name) - if not bywith: - bywith = byname[name] = {} - - - rkey = ikey, name, with # The full key has all 4 - if (with not in bywith - or - (rkey not in registered or registered[rkey].extends(provided)) - ): - # This is either a new entry or it is an entry for a more - # general interface that is closer provided than what we had - # before - registered[rkey] = provided - bywith[with] = object - - for b in target.__bases__: - _add_multi_adapter(with, name, b, provided, implied, - registered, object) - -def _add_named_sub_adapter(target, implied, objects): - key = ('s', target) - implied[key] = implied.get(key, ()) + objects - - for b in target.__bases__: - _add_named_sub_adapter(b, implied, objects) - -def _add_multi_sub_adapter(with, target, implied, objects): - key = 's', target, (len(with) + 1) - bywith = implied.get(key) - if not bywith: - bywith = implied[key] = {} - - bywith[with] = bywith.get(with, ()) + objects - - for b in target.__bases__: - _add_multi_sub_adapter(with, b, implied, objects) diff --git a/src/zope/interface/adapter.txt b/src/zope/interface/adapter.txt deleted file mode 100644 index 6170452..0000000 --- a/src/zope/interface/adapter.txt +++ /dev/null @@ -1,514 +0,0 @@ -================ -Adapter Registry -================ - -Adapter registries provide a way to register objects that depend on -one or more interface specifications and provide (perhaps indirectly) -some interface. In addition, the registrations have names. (You can -think of the names as qualifiers of the provided interfaces.) - -The term "interface specification" refers both to interfaces and to -interface declarations, such as declarations of interfaces implemented -by a class. - - -Single Adapters -=============== - -Let's look at a simple example, using a single required specification:: - - >>> from zope.interface.adapter import AdapterRegistry - >>> import zope.interface - - >>> class IR1(zope.interface.Interface): - ... pass - >>> class IP1(zope.interface.Interface): - ... pass - >>> class IP2(IP1): - ... pass - - >>> registry = AdapterRegistry() - -We'll register an object that depends on IR1 and "provides" IP2:: - - >>> registry.register([IR1], IP2, '', 12) - -Given the registration, we can look it up again:: - - >>> registry.lookup([IR1], IP2, '') - 12 - -Note that we used an integer in the example. In real applications, -one would use some objects that actually depend on or provide -interfaces. The registry doesn't care about what gets registered, so -we'll use integers and strings to keep the examples simple. There is -one exception. Registering a value of None unregisters any -previously-registered value. - -If an object depends on a specification, it can be looked up with a -specification that extends the specification that it depends on:: - - >>> class IR2(IR1): - ... pass - >>> registry.lookup([IR2], IP2, '') - 12 - -We can use a class implementation specification to look up the object:: - - >>> class C2: - ... zope.interface.implements(IR2) - - >>> registry.lookup([zope.interface.implementedBy(C2)], IP2, '') - 12 - - -and it can be looked up for interfaces that its provided interface -extends:: - - >>> registry.lookup([IR1], IP1, '') - 12 - >>> registry.lookup([IR2], IP1, '') - 12 - -But if you require a specification that doesn't extend the specification the -object depends on, you won't get anything:: - - >>> registry.lookup([zope.interface.Interface], IP1, '') - -By the way, you can pass a default value to lookup:: - - >>> registry.lookup([zope.interface.Interface], IP1, '', 42) - 42 - -If you try to get an interface the object doesn't provide, you also -won't get anything:: - - >>> class IP3(IP2): - ... pass - >>> registry.lookup([IR1], IP3, '') - -You also won't get anything if you use the wrong name:: - - >>> registry.lookup([IR1], IP1, 'bob') - >>> registry.register([IR1], IP2, 'bob', "Bob's 12") - >>> registry.lookup([IR1], IP1, 'bob') - "Bob's 12" - -You can leave the name off when doing a lookup:: - - >>> registry.lookup([IR1], IP1) - 12 - -If we register an object that provides IP1:: - - >>> registry.register([IR1], IP1, '', 11) - -then that object will be prefered over O(12):: - - >>> registry.lookup([IR1], IP1, '') - 11 - -Also, if we register an object for IR2, then that will be prefered -when using IR2:: - - >>> registry.register([IR2], IP1, '', 21) - >>> registry.lookup([IR2], IP1, '') - 21 - -lookup1 -------- - -Lookup of single adapters is common enough that there is a specialized -version of lookup that takes a single required interface:: - - >>> registry.lookup1(IR2, IP1, '') - 21 - >>> registry.lookup1(IR2, IP1) - 21 - -Actual Adaptation ------------------ - -The adapter registry is intended to support adaptation, where one -object that implements an interface is adapted to another object that -supports a different interface. The adapter registry supports the -computation of adapters. In this case, we have to register adapter -factories:: - - >>> class IR(zope.interface.Interface): - ... pass - - >>> class X: - ... zope.interface.implements(IR) - - >>> class Y: - ... zope.interface.implements(IP1) - ... def __init__(self, context): - ... self.context = context - - >>> registry.register([IR], IP1, '', Y) - -In this case, we registered a class as the factory. Now we can call -`queryAdapter` to get the adapted object:: - - >>> x = X() - >>> y = registry.queryAdapter(x, IP1) - >>> y.__class__.__name__ - 'Y' - >>> y.context is x - True - -We can register and lookup by name too:: - - >>> class Y2(Y): - ... pass - - >>> registry.register([IR], IP1, 'bob', Y2) - >>> y = registry.queryAdapter(x, IP1, 'bob') - >>> y.__class__.__name__ - 'Y2' - >>> y.context is x - True - -When the adapter factory produces `None`, then this is treated as if no -adapter has been found. This allows us to prevent adaptation (when desired) -and let the adapter factory determine whether adaptation is possible based on -the state of the object being adapted. - - >>> def factory(context): - ... if context.name == 'object': - ... return 'adapter' - ... return None - - >>> class Object(object): - ... zope.interface.implements(IR) - ... name = 'object' - - >>> registry.register([IR], IP1, 'conditional', factory) - >>> obj = Object() - >>> registry.queryAdapter(obj, IP1, 'conditional') - 'adapter' - >>> obj.name = 'no object' - >>> registry.queryAdapter(obj, IP1, 'conditional') is None - True - >>> registry.queryAdapter(obj, IP1, 'conditional', 'default') - 'default' - -An alternate method that provides the same function as `queryAdapter()` is -`adapter_hook()`:: - - >>> y = registry.adapter_hook(IP1, x) - >>> y.__class__.__name__ - 'Y' - >>> y.context is x - True - >>> y = registry.adapter_hook(IP1, x, 'bob') - >>> y.__class__.__name__ - 'Y2' - >>> y.context is x - True - -The `adapter_hook()` simply switches the order of the object and -interface arguments. It is used to hook into the interface call -mechanism. - - -Default Adapters ----------------- - -Sometimes, you want to provide an adapter that will adapt anything. -For that, provide None as the required interface:: - - >>> registry.register([None], IP1, '', 1) - -then we can use that adapter for interfaces we don't have specific -adapters for:: - - >>> class IQ(zope.interface.Interface): - ... pass - >>> registry.lookup([IQ], IP1, '') - 1 - -Of course, specific adapters are still used when applicable:: - - >>> registry.lookup([IR2], IP1, '') - 21 - -Class adapters --------------- - -You can register adapters for class declarations, which is almost the -same as registering them for a class:: - - >>> registry.register([zope.interface.implementedBy(C2)], IP1, '', 'C21') - >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '') - 'C21' - -Dict adapters -------------- - -At some point it was impossible to register dictionary-based adapters due a -bug. Let's make sure this works now: - - >>> adapter = {} - >>> registry.register((), IQ, '', adapter) - >>> registry.lookup((), IQ, '') is adapter - True - -Unregistering -------------- - -You can unregister by registering None, rather than an object:: - - >>> registry.register([zope.interface.implementedBy(C2)], IP1, '', None) - >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '') - 21 - -Of course, this means that None can't be registered. This is an -exception to the statement, made earlier, that the registry doesn't -care what gets registered. - -Multi-adapters -============== - -You can adapt multiple specifications:: - - >>> registry.register([IR1, IQ], IP2, '', '1q2') - >>> registry.lookup([IR1, IQ], IP2, '') - '1q2' - >>> registry.lookup([IR2, IQ], IP1, '') - '1q2' - - >>> class IS(zope.interface.Interface): - ... pass - >>> registry.lookup([IR2, IS], IP1, '') - - >>> class IQ2(IQ): - ... pass - - >>> registry.lookup([IR2, IQ2], IP1, '') - '1q2' - - >>> registry.register([IR1, IQ2], IP2, '', '1q22') - >>> registry.lookup([IR2, IQ2], IP1, '') - '1q22' - -Multi-adaptation ----------------- - -You can adapt multiple objects:: - - >>> class Q: - ... zope.interface.implements(IQ) - -As with single adapters, we register a factory, which is often a class:: - - >>> class IM(zope.interface.Interface): - ... pass - >>> class M: - ... zope.interface.implements(IM) - ... def __init__(self, x, q): - ... self.x, self.q = x, q - >>> registry.register([IR, IQ], IM, '', M) - -And then we can call `queryMultiAdapter` to compute an adapter:: - - >>> q = Q() - >>> m = registry.queryMultiAdapter((x, q), IM) - >>> m.__class__.__name__ - 'M' - >>> m.x is x and m.q is q - True - -and, of course, we can use names:: - - >>> class M2(M): - ... pass - >>> registry.register([IR, IQ], IM, 'bob', M2) - >>> m = registry.queryMultiAdapter((x, q), IM, 'bob') - >>> m.__class__.__name__ - 'M2' - >>> m.x is x and m.q is q - True - -Default Adapters ----------------- - -As with single adapters, you can define default adapters by specifying -None for the *first* specification:: - - >>> registry.register([None, IQ], IP2, '', 'q2') - >>> registry.lookup([IS, IQ], IP2, '') - 'q2' - -Null Adapters -============= - -You can also adapt no specification:: - - >>> registry.register([], IP2, '', 2) - >>> registry.lookup([], IP2, '') - 2 - >>> registry.lookup([], IP1, '') - 2 - -Listing named adapters ----------------------- - -Adapters are named. Sometimes, it's useful to get all of the named -adapters for given interfaces:: - - >>> adapters = list(registry.lookupAll([IR1], IP1)) - >>> adapters.sort() - >>> adapters - [(u'', 11), (u'bob', "Bob's 12")] - -This works for multi-adapters too:: - - >>> registry.register([IR1, IQ2], IP2, 'bob', '1q2 for bob') - >>> adapters = list(registry.lookupAll([IR2, IQ2], IP1)) - >>> adapters.sort() - >>> adapters - [(u'', '1q22'), (u'bob', '1q2 for bob')] - -And even null adapters:: - - >>> registry.register([], IP2, 'bob', 3) - >>> adapters = list(registry.lookupAll([], IP1)) - >>> adapters.sort() - >>> adapters - [(u'', 2), (u'bob', 3)] - -Subscriptions -============= - -Normally, we want to look up an object that most-closely matches a -specification. Sometimes, we want to get all of the objects that -match some specification. We use subscriptions for this. We -subscribe objects against specifications and then later find all of -the subscribed objects:: - - >>> registry.subscribe([IR1], IP2, 'sub12 1') - >>> registry.subscriptions([IR1], IP2) - ['sub12 1'] - -Note that, unlike regular adapters, subscriptions are unnamed. - -The order of returned subscriptions is not specified. - -You can have multiple subscribers for the same specification:: - - >>> registry.subscribe([IR1], IP2, 'sub12 2') - >>> subs = registry.subscriptions([IR1], IP2) - >>> subs.sort() - >>> subs - ['sub12 1', 'sub12 2'] - -You can register subscribers for all specifications using None:: - - >>> registry.subscribe([None], IP1, 'sub_1') - >>> subs = registry.subscriptions([IR2], IP1) - >>> subs.sort() - >>> subs - ['sub12 1', 'sub12 2', 'sub_1'] - -Subscriptions may be combined over multiple compatible specifications:: - - >>> subs = registry.subscriptions([IR2], IP1) - >>> subs.sort() - >>> subs - ['sub12 1', 'sub12 2', 'sub_1'] - >>> registry.subscribe([IR1], IP1, 'sub11') - >>> subs = registry.subscriptions([IR2], IP1) - >>> subs.sort() - >>> subs - ['sub11', 'sub12 1', 'sub12 2', 'sub_1'] - >>> registry.subscribe([IR2], IP2, 'sub22') - >>> subs = registry.subscriptions([IR2], IP1) - >>> subs.sort() - >>> subs - ['sub11', 'sub12 1', 'sub12 2', 'sub22', 'sub_1'] - >>> subs = registry.subscriptions([IR2], IP2) - >>> subs.sort() - >>> subs - ['sub12 1', 'sub12 2', 'sub22'] - -Subscriptions can be on multiple specifications:: - - >>> registry.subscribe([IR1, IQ], IP2, 'sub1q2') - >>> registry.subscriptions([IR1, IQ], IP2) - ['sub1q2'] - -As with single subscriptions and non-subscription adapters, you can -specify None for the first required interface, to specify a default:: - - >>> registry.subscribe([None, IQ], IP2, 'sub_q2') - >>> registry.subscriptions([IS, IQ], IP2) - ['sub_q2'] - >>> subs = registry.subscriptions([IR1, IQ], IP2) - >>> subs.sort() - >>> subs - ['sub1q2', 'sub_q2'] - -You can have subscriptions that are indepenent of any specifications:: - - >>> registry.subscriptions([], IP1) - [] - - >>> registry.subscribe([], IP2, 'sub2') - >>> registry.subscriptions([], IP1) - ['sub2'] - >>> registry.subscribe([], IP1, 'sub1') - >>> subs = registry.subscriptions([], IP1) - >>> subs.sort() - >>> subs - ['sub1', 'sub2'] - >>> registry.subscriptions([], IP2) - ['sub2'] - - -Subscription adapters ---------------------- - -We normally register adapter factories, which then allow us to compute -adapters, but with subscriptions, we get multiple adapters. Here's an -example of multiple-object subscribers:: - - >>> registry.subscribe([IR, IQ], IM, M) - >>> registry.subscribe([IR, IQ], IM, M2) - - >>> subscribers = registry.subscribers((x, q), IM) - >>> len(subscribers) - 2 - >>> class_names = [s.__class__.__name__ for s in subscribers] - >>> class_names.sort() - >>> class_names - ['M', 'M2'] - >>> [(s.x is x and s.q is q) for s in subscribers] - [True, True] - -adapter factory subcribers can't return None values - - >>> def M3(x, y): - ... return None - - >>> registry.subscribe([IR, IQ], IM, M3) - >>> subscribers = registry.subscribers((x, q), IM) - >>> len(subscribers) - 2 - -Handlers --------- - -A handler is a subscriber factory that doesn't produce any normal -output. It returns None. A handler is unlike adapters in that it does -all of its work when the factory is called. - -To register a handler, simply provide None as the provided interface:: - - >>> def handler(event): - ... print 'handler', event - - >>> registry.subscribe([IR1], None, handler) - >>> registry.subscriptions([IR1], None) == [handler] - True diff --git a/src/zope/interface/advice.py b/src/zope/interface/advice.py deleted file mode 100644 index 6a06167..0000000 --- a/src/zope/interface/advice.py +++ /dev/null @@ -1,192 +0,0 @@ -############################################################################## -# -# Copyright (c) 2003 Zope Corporation 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. -# -############################################################################## -"""Class advice. - -This module was adapted from 'protocols.advice', part of the Python -Enterprise Application Kit (PEAK). Please notify the PEAK authors -(pje@telecommunity.com and tsarna@sarna.org) if bugs are found or -Zope-specific changes are required, so that the PEAK version of this module -can be kept in sync. - -PEAK is a Python application framework that interoperates with (but does -not require) Zope 3 and Twisted. It provides tools for manipulating UML -models, object-relational persistence, aspect-oriented programming, and more. -Visit the PEAK home page at http://peak.telecommunity.com for more information. - -$Id$ -""" - -from types import ClassType, FunctionType -import sys - -def getFrameInfo(frame): - """Return (kind,module,locals,globals) for a frame - - 'kind' is one of "exec", "module", "class", "function call", or "unknown". - """ - - f_locals = frame.f_locals - f_globals = frame.f_globals - - sameNamespace = f_locals is f_globals - hasModule = '__module__' in f_locals - hasName = '__name__' in f_globals - - sameName = hasModule and hasName - sameName = sameName and f_globals['__name__']==f_locals['__module__'] - - module = hasName and sys.modules.get(f_globals['__name__']) or None - - namespaceIsModule = module and module.__dict__ is f_globals - - if not namespaceIsModule: - # some kind of funky exec - kind = "exec" - elif sameNamespace and not hasModule: - kind = "module" - elif sameName and not sameNamespace: - kind = "class" - elif not sameNamespace: - kind = "function call" - else: - # How can you have f_locals is f_globals, and have '__module__' set? - # This is probably module-level code, but with a '__module__' variable. - kind = "unknown" - return kind, module, f_locals, f_globals - - -def addClassAdvisor(callback, depth=2): - """Set up 'callback' to be passed the containing class upon creation - - This function is designed to be called by an "advising" function executed - in a class suite. The "advising" function supplies a callback that it - wishes to have executed when the containing class is created. The - callback will be given one argument: the newly created containing class. - The return value of the callback will be used in place of the class, so - the callback should return the input if it does not wish to replace the - class. - - The optional 'depth' argument to this function determines the number of - frames between this function and the targeted class suite. 'depth' - defaults to 2, since this skips this function's frame and one calling - function frame. If you use this function from a function called directly - in the class suite, the default will be correct, otherwise you will need - to determine the correct depth yourself. - - This function works by installing a special class factory function in - place of the '__metaclass__' of the containing class. Therefore, only - callbacks *after* the last '__metaclass__' assignment in the containing - class will be executed. Be sure that classes using "advising" functions - declare any '__metaclass__' *first*, to ensure all callbacks are run.""" - - frame = sys._getframe(depth) - kind, module, caller_locals, caller_globals = getFrameInfo(frame) - - # This causes a problem when zope interfaces are used from doctest. - # In these cases, kind == "exec". - # - #if kind != "class": - # raise SyntaxError( - # "Advice must be in the body of a class statement" - # ) - - previousMetaclass = caller_locals.get('__metaclass__') - defaultMetaclass = caller_globals.get('__metaclass__', ClassType) - - - def advise(name, bases, cdict): - - if '__metaclass__' in cdict: - del cdict['__metaclass__'] - - if previousMetaclass is None: - if bases: - # find best metaclass or use global __metaclass__ if no bases - meta = determineMetaclass(bases) - else: - meta = defaultMetaclass - - elif isClassAdvisor(previousMetaclass): - # special case: we can't compute the "true" metaclass here, - # so we need to invoke the previous metaclass and let it - # figure it out for us (and apply its own advice in the process) - meta = previousMetaclass - - else: - meta = determineMetaclass(bases, previousMetaclass) - - newClass = meta(name,bases,cdict) - - # this lets the callback replace the class completely, if it wants to - return callback(newClass) - - # introspection data only, not used by inner function - advise.previousMetaclass = previousMetaclass - advise.callback = callback - - # install the advisor - caller_locals['__metaclass__'] = advise - - -def isClassAdvisor(ob): - """True if 'ob' is a class advisor function""" - return isinstance(ob,FunctionType) and hasattr(ob,'previousMetaclass') - - -def determineMetaclass(bases, explicit_mc=None): - """Determine metaclass from 1+ bases and optional explicit __metaclass__""" - - meta = [getattr(b,'__class__',type(b)) for b in bases] - - if explicit_mc is not None: - # The explicit metaclass needs to be verified for compatibility - # as well, and allowed to resolve the incompatible bases, if any - meta.append(explicit_mc) - - if len(meta)==1: - # easy case - return meta[0] - - candidates = minimalBases(meta) # minimal set of metaclasses - - if not candidates: - # they're all "classic" classes - return ClassType - - elif len(candidates)>1: - # We could auto-combine, but for now we won't... - raise TypeError("Incompatible metatypes",bases) - - # Just one, return it - return candidates[0] - - -def minimalBases(classes): - """Reduce a list of base classes to its ordered minimum equivalent""" - - classes = [c for c in classes if c is not ClassType] - candidates = [] - - for m in classes: - for n in classes: - if issubclass(n,m) and m is not n: - break - else: - # m has no subclasses in 'classes' - if m in candidates: - candidates.remove(m) # ensure that we're later in the list - candidates.append(m) - - return candidates - diff --git a/src/zope/interface/common/__init__.py b/src/zope/interface/common/__init__.py deleted file mode 100644 index b711d36..0000000 --- a/src/zope/interface/common/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# -# This file is necessary to make this directory a package. diff --git a/src/zope/interface/common/idatetime.py b/src/zope/interface/common/idatetime.py deleted file mode 100644 index f0db2eb..0000000 --- a/src/zope/interface/common/idatetime.py +++ /dev/null @@ -1,577 +0,0 @@ -############################################################################## -# Copyright (c) 2002 Zope Corporation 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. -############################################################################## -"""Datetime interfaces. - -This module is called idatetime because if it were called datetime the import -of the real datetime would fail. - -$Id$ -""" - -from zope.interface import Interface, Attribute -from zope.interface import classImplements, directlyProvides - -from datetime import timedelta, date, datetime, time, tzinfo - - -class ITimeDeltaClass(Interface): - """This is the timedelta class interface.""" - - min = Attribute("The most negative timedelta object") - - max = Attribute("The most positive timedelta object") - - resolution = Attribute( - "The smallest difference between non-equal timedelta objects") - - -class ITimeDelta(ITimeDeltaClass): - """Represent the difference between two datetime objects. - - Supported operators: - - - add, subtract timedelta - - unary plus, minus, abs - - compare to timedelta - - multiply, divide by int/long - - In addition, datetime supports subtraction of two datetime objects - returning a timedelta, and addition or subtraction of a datetime - and a timedelta giving a datetime. - - Representation: (days, seconds, microseconds). - """ - - days = Attribute("Days between -999999999 and 999999999 inclusive") - - seconds = Attribute("Seconds between 0 and 86399 inclusive") - - microseconds = Attribute("Microseconds between 0 and 999999 inclusive") - - -class IDateClass(Interface): - """This is the date class interface.""" - - min = Attribute("The earliest representable date") - - max = Attribute("The latest representable date") - - resolution = Attribute( - "The smallest difference between non-equal date objects") - - def today(): - """Return the current local time. - - This is equivalent to date.fromtimestamp(time.time())""" - - def fromtimestamp(timestamp): - """Return the local date from a POSIX timestamp (like time.time()) - - This may raise ValueError, if the timestamp is out of the range of - values supported by the platform C localtime() function. It's common - for this to be restricted to years from 1970 through 2038. Note that - on non-POSIX systems that include leap seconds in their notion of a - timestamp, leap seconds are ignored by fromtimestamp(). - """ - - def fromordinal(ordinal): - """Return the date corresponding to the proleptic Gregorian ordinal. - - January 1 of year 1 has ordinal 1. ValueError is raised unless - 1 <= ordinal <= date.max.toordinal(). - For any date d, date.fromordinal(d.toordinal()) == d. - """ - - -class IDate(IDateClass): - """Represents a date (year, month and day) in an idealized calendar. - - Operators: - - __repr__, __str__ - __cmp__, __hash__ - __add__, __radd__, __sub__ (add/radd only with timedelta arg) - """ - - year = Attribute("Between MINYEAR and MAXYEAR inclusive.") - - month = Attribute("Between 1 and 12 inclusive") - - day = Attribute( - "Between 1 and the number of days in the given month of the given year.") - - def replace(year, month, day): - """Return a date with the same value. - - Except for those members given new values by whichever keyword - arguments are specified. For example, if d == date(2002, 12, 31), then - d.replace(day=26) == date(2000, 12, 26). - """ - - def timetuple(): - """Return a 9-element tuple of the form returned by time.localtime(). - - The hours, minutes and seconds are 0, and the DST flag is -1. - d.timetuple() is equivalent to - (d.year, d.month, d.day, 0, 0, 0, d.weekday(), d.toordinal() - - date(d.year, 1, 1).toordinal() + 1, -1) - """ - - def toordinal(): - """Return the proleptic Gregorian ordinal of the date - - January 1 of year 1 has ordinal 1. For any date object d, - date.fromordinal(d.toordinal()) == d. - """ - - def weekday(): - """Return the day of the week as an integer. - - Monday is 0 and Sunday is 6. For example, - date(2002, 12, 4).weekday() == 2, a Wednesday. - - See also isoweekday(). - """ - - def isoweekday(): - """Return the day of the week as an integer. - - Monday is 1 and Sunday is 7. For example, - date(2002, 12, 4).isoweekday() == 3, a Wednesday. - - See also weekday(), isocalendar(). - """ - - def isocalendar(): - """Return a 3-tuple, (ISO year, ISO week number, ISO weekday). - - The ISO calendar is a widely used variant of the Gregorian calendar. - See http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm for a good - explanation. - - The ISO year consists of 52 or 53 full weeks, and where a week starts - on a Monday and ends on a Sunday. The first week of an ISO year is the - first (Gregorian) calendar week of a year containing a Thursday. This - is called week number 1, and the ISO year of that Thursday is the same - as its Gregorian year. - - For example, 2004 begins on a Thursday, so the first week of ISO year - 2004 begins on Monday, 29 Dec 2003 and ends on Sunday, 4 Jan 2004, so - that date(2003, 12, 29).isocalendar() == (2004, 1, 1) and - date(2004, 1, 4).isocalendar() == (2004, 1, 7). - """ - - def isoformat(): - """Return a string representing the date in ISO 8601 format. - - This is 'YYYY-MM-DD'. - For example, date(2002, 12, 4).isoformat() == '2002-12-04'. - """ - - def __str__(): - """For a date d, str(d) is equivalent to d.isoformat().""" - - def ctime(): - """Return a string representing the date. - - For example date(2002, 12, 4).ctime() == 'Wed Dec 4 00:00:00 2002'. - d.ctime() is equivalent to time.ctime(time.mktime(d.timetuple())) - on platforms where the native C ctime() function - (which time.ctime() invokes, but which date.ctime() does not invoke) - conforms to the C standard. - """ - - def strftime(format): - """Return a string representing the date. - - Controlled by an explicit format string. Format codes referring to - hours, minutes or seconds will see 0 values. - """ - - -class IDateTimeClass(Interface): - """This is the datetime class interface.""" - - min = Attribute("The earliest representable datetime") - - max = Attribute("The latest representable datetime") - - resolution = Attribute( - "The smallest possible difference between non-equal datetime objects") - - def today(): - """Return the current local datetime, with tzinfo None. - - This is equivalent to datetime.fromtimestamp(time.time()). - See also now(), fromtimestamp(). - """ - - def now(tz=None): - """Return the current local date and time. - - If optional argument tz is None or not specified, this is like today(), - but, if possible, supplies more precision than can be gotten from going - through a time.time() timestamp (for example, this may be possible on - platforms supplying the C gettimeofday() function). - - Else tz must be an instance of a class tzinfo subclass, and the current - date and time are converted to tz's time zone. In this case the result - is equivalent to tz.fromutc(datetime.utcnow().replace(tzinfo=tz)). - - See also today(), utcnow(). - """ - - def utcnow(): - """Return the current UTC date and time, with tzinfo None. - - This is like now(), but returns the current UTC date and time, as a - naive datetime object. - - See also now(). - """ - - def fromtimestamp(timestamp, tz=None): - """Return the local date and time corresponding to the POSIX timestamp. - - Same as is returned by time.time(). If optional argument tz is None or - not specified, the timestamp is converted to the platform's local date - and time, and the returned datetime object is naive. - - Else tz must be an instance of a class tzinfo subclass, and the - timestamp is converted to tz's time zone. In this case the result is - equivalent to - tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz)). - - fromtimestamp() may raise ValueError, if the timestamp is out of the - range of values supported by the platform C localtime() or gmtime() - functions. It's common for this to be restricted to years in 1970 - through 2038. Note that on non-POSIX systems that include leap seconds - in their notion of a timestamp, leap seconds are ignored by - fromtimestamp(), and then it's possible to have two timestamps - differing by a second that yield identical datetime objects. - - See also utcfromtimestamp(). - """ - - def utcfromtimestamp(timestamp): - """Return the UTC datetime from the POSIX timestamp with tzinfo None. - - This may raise ValueError, if the timestamp is out of the range of - values supported by the platform C gmtime() function. It's common for - this to be restricted to years in 1970 through 2038. - - See also fromtimestamp(). - """ - - def fromordinal(ordinal): - """Return the datetime from the proleptic Gregorian ordinal. - - January 1 of year 1 has ordinal 1. ValueError is raised unless - 1 <= ordinal <= datetime.max.toordinal(). - The hour, minute, second and microsecond of the result are all 0, and - tzinfo is None. - """ - - def combine(date, time): - """Return a new datetime object. - - Its date members are equal to the given date object's, and whose time - and tzinfo members are equal to the given time object's. For any - datetime object d, d == datetime.combine(d.date(), d.timetz()). - If date is a datetime object, its time and tzinfo members are ignored. - """ - - -class IDateTime(IDate, IDateTimeClass): - """Object contains all the information from a date object and a time object. - """ - - year = Attribute("Year between MINYEAR and MAXYEAR inclusive") - - month = Attribute("Month between 1 and 12 inclusive") - - day = Attribute( - "Day between 1 and the number of days in the given month of the year") - - hour = Attribute("Hour in range(24)") - - minute = Attribute("Minute in range(60)") - - second = Attribute("Second in range(60)") - - microsecond = Attribute("Microsecond in range(1000000)") - - tzinfo = Attribute( - """The object passed as the tzinfo argument to the datetime constructor - or None if none was passed""") - - def date(): - """Return date object with same year, month and day.""" - - def time(): - """Return time object with same hour, minute, second, microsecond. - - tzinfo is None. See also method timetz(). - """ - - def timetz(): - """Return time object with same hour, minute, second, microsecond, - and tzinfo. - - See also method time(). - """ - - def replace(year, month, day, hour, minute, second, microsecond, tzinfo): - """Return a datetime with the same members, except for those members - given new values by whichever keyword arguments are specified. - - Note that tzinfo=None can be specified to create a naive datetime from - an aware datetime with no conversion of date and time members. - """ - - def astimezone(tz): - """Return a datetime object with new tzinfo member tz, adjusting the - date and time members so the result is the same UTC time as self, but - in tz's local time. - - tz must be an instance of a tzinfo subclass, and its utcoffset() and - dst() methods must not return None. self must be aware (self.tzinfo - must not be None, and self.utcoffset() must not return None). - - If self.tzinfo is tz, self.astimezone(tz) is equal to self: no - adjustment of date or time members is performed. Else the result is - local time in time zone tz, representing the same UTC time as self: - after astz = dt.astimezone(tz), astz - astz.utcoffset() - will usually have the same date and time members as dt - dt.utcoffset(). - The discussion of class tzinfo explains the cases at Daylight Saving - Time transition boundaries where this cannot be achieved (an issue only - if tz models both standard and daylight time). - - If you merely want to attach a time zone object tz to a datetime dt - without adjustment of date and time members, use dt.replace(tzinfo=tz). - If you merely want to remove the time zone object from an aware - datetime dt without conversion of date and time members, use - dt.replace(tzinfo=None). - - Note that the default tzinfo.fromutc() method can be overridden in a - tzinfo subclass to effect the result returned by astimezone(). - """ - - def utcoffset(): - """Return the timezone offset in minutes east of UTC (negative west of - UTC).""" - - def dst(): - """Return 0 if DST is not in effect, or the DST offset (in minutes - eastward) if DST is in effect. - """ - - def tzname(): - """Return the timezone name.""" - - def timetuple(): - """Return a 9-element tuple of the form returned by time.localtime().""" - - def utctimetuple(): - """Return UTC time tuple compatilble with time.gmtimr().""" - - def toordinal(): - """Return the proleptic Gregorian ordinal of the date. - - The same as self.date().toordinal(). - """ - - def weekday(): - """Return the day of the week as an integer. - - Monday is 0 and Sunday is 6. The same as self.date().weekday(). - See also isoweekday(). - """ - - def isoweekday(): - """Return the day of the week as an integer. - - Monday is 1 and Sunday is 7. The same as self.date().isoweekday. - See also weekday(), isocalendar(). - """ - - def isocalendar(): - """Return a 3-tuple, (ISO year, ISO week number, ISO weekday). - - The same as self.date().isocalendar(). - """ - - def isoformat(sep='T'): - """Return a string representing the date and time in ISO 8601 format. - - YYYY-MM-DDTHH:MM:SS.mmmmmm or YYYY-MM-DDTHH:MM:SS if microsecond is 0 - - If utcoffset() does not return None, a 6-character string is appended, - giving the UTC offset in (signed) hours and minutes: - - YYYY-MM-DDTHH:MM:SS.mmmmmm+HH:MM or YYYY-MM-DDTHH:MM:SS+HH:MM - if microsecond is 0. - - The optional argument sep (default 'T') is a one-character separator, - placed between the date and time portions of the result. - """ - - def __str__(): - """For a datetime instance d, str(d) is equivalent to d.isoformat(' '). - """ - - def ctime(): - """Return a string representing the date and time. - - datetime(2002, 12, 4, 20, 30, 40).ctime() == 'Wed Dec 4 20:30:40 2002'. - d.ctime() is equivalent to time.ctime(time.mktime(d.timetuple())) on - platforms where the native C ctime() function (which time.ctime() - invokes, but which datetime.ctime() does not invoke) conforms to the - C standard. - """ - - def strftime(format): - """Return a string representing the date and time. - - This is controlled by an explicit format string. - """ - - -class ITimeClass(Interface): - """This is the time class interface.""" - - min = Attribute("The earliest representable time") - - max = Attribute("The latest representable time") - - resolution = Attribute( - "The smallest possible difference between non-equal time objects") - - -class ITime(ITimeClass): - """Represent time with time zone. - - Operators: - - __repr__, __str__ - __cmp__, __hash__ - """ - - hour = Attribute("Hour in range(24)") - - minute = Attribute("Minute in range(60)") - - second = Attribute("Second in range(60)") - - microsecond = Attribute("Microsecond in range(1000000)") - - tzinfo = Attribute( - """The object passed as the tzinfo argument to the time constructor - or None if none was passed.""") - - def replace(hour, minute, second, microsecond, tzinfo): - """Return a time with the same value. - - Except for those members given new values by whichever keyword - arguments are specified. Note that tzinfo=None can be specified - to create a naive time from an aware time, without conversion of the - time members. - """ - - def isoformat(): - """Return a string representing the time in ISO 8601 format. - - That is HH:MM:SS.mmmmmm or, if self.microsecond is 0, HH:MM:SS - If utcoffset() does not return None, a 6-character string is appended, - giving the UTC offset in (signed) hours and minutes: - HH:MM:SS.mmmmmm+HH:MM or, if self.microsecond is 0, HH:MM:SS+HH:MM - """ - - def __str__(): - """For a time t, str(t) is equivalent to t.isoformat().""" - - def strftime(format): - """Return a string representing the time. - - This is controlled by an explicit format string. - """ - - def utcoffset(): - """Return the timezone offset in minutes east of UTC (negative west of - UTC). - - If tzinfo is None, returns None, else returns - self.tzinfo.utcoffset(None), and raises an exception if the latter - doesn't return None or a timedelta object representing a whole number - of minutes with magnitude less than one day. - """ - - def dst(): - """Return 0 if DST is not in effect, or the DST offset (in minutes - eastward) if DST is in effect. - - If tzinfo is None, returns None, else returns self.tzinfo.dst(None), - and raises an exception if the latter doesn't return None, or a - timedelta object representing a whole number of minutes with - magnitude less than one day. - """ - - def tzname(): - """Return the timezone name. - - If tzinfo is None, returns None, else returns self.tzinfo.tzname(None), - or raises an exception if the latter doesn't return None or a string - object. - """ - - -class ITZInfo(Interface): - """Time zone info class. - """ - - def utcoffset(dt): - """Return offset of local time from UTC, in minutes east of UTC. - - If local time is west of UTC, this should be negative. - Note that this is intended to be the total offset from UTC; - for example, if a tzinfo object represents both time zone and DST - adjustments, utcoffset() should return their sum. If the UTC offset - isn't known, return None. Else the value returned must be a timedelta - object specifying a whole number of minutes in the range -1439 to 1439 - inclusive (1440 = 24*60; the magnitude of the offset must be less - than one day). - """ - - def dst(dt): - """Return the daylight saving time (DST) adjustment, in minutes east - of UTC, or None if DST information isn't known. - """ - - def tzname(dt): - """Return the time zone name corresponding to the datetime object as - a string. - """ - - def fromutc(dt): - """Return an equivalent datetime in self's local time.""" - - -classImplements(timedelta, ITimeDelta) -classImplements(date, IDate) -classImplements(datetime, IDateTime) -classImplements(time, ITime) -classImplements(tzinfo, ITZInfo) - -## directlyProvides(timedelta, ITimeDeltaClass) -## directlyProvides(date, IDateClass) -## directlyProvides(datetime, IDateTimeClass) -## directlyProvides(time, ITimeClass) diff --git a/src/zope/interface/common/interfaces.py b/src/zope/interface/common/interfaces.py deleted file mode 100644 index 345320b..0000000 --- a/src/zope/interface/common/interfaces.py +++ /dev/null @@ -1,98 +0,0 @@ -############################################################################## -# -# Copyright (c) 2003 Zope Corporation 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. -# -############################################################################## -"""Interfaces for standard python exceptions - -$Id$ -""" -from zope.interface import Interface -from zope.interface import classImplements - -class IException(Interface): pass -class IStandardError(IException): pass -class IWarning(IException): pass -class ISyntaxError(IStandardError): pass -class ILookupError(IStandardError): pass -class IValueError(IStandardError): pass -class IRuntimeError(IStandardError): pass -class IArithmeticError(IStandardError): pass -class IAssertionError(IStandardError): pass -class IAttributeError(IStandardError): pass -class IDeprecationWarning(IWarning): pass -class IEOFError(IStandardError): pass -class IEnvironmentError(IStandardError): pass -class IFloatingPointError(IArithmeticError): pass -class IIOError(IEnvironmentError): pass -class IImportError(IStandardError): pass -class IIndentationError(ISyntaxError): pass -class IIndexError(ILookupError): pass -class IKeyError(ILookupError): pass -class IKeyboardInterrupt(IStandardError): pass -class IMemoryError(IStandardError): pass -class INameError(IStandardError): pass -class INotImplementedError(IRuntimeError): pass -class IOSError(IEnvironmentError): pass -class IOverflowError(IArithmeticError): pass -class IOverflowWarning(IWarning): pass -class IReferenceError(IStandardError): pass -class IRuntimeWarning(IWarning): pass -class IStopIteration(IException): pass -class ISyntaxWarning(IWarning): pass -class ISystemError(IStandardError): pass -class ISystemExit(IException): pass -class ITabError(IIndentationError): pass -class ITypeError(IStandardError): pass -class IUnboundLocalError(INameError): pass -class IUnicodeError(IValueError): pass -class IUserWarning(IWarning): pass -class IZeroDivisionError(IArithmeticError): pass - -classImplements(ArithmeticError, IArithmeticError) -classImplements(AssertionError, IAssertionError) -classImplements(AttributeError, IAttributeError) -classImplements(DeprecationWarning, IDeprecationWarning) -classImplements(EnvironmentError, IEnvironmentError) -classImplements(EOFError, IEOFError) -classImplements(Exception, IException) -classImplements(FloatingPointError, IFloatingPointError) -classImplements(ImportError, IImportError) -classImplements(IndentationError, IIndentationError) -classImplements(IndexError, IIndexError) -classImplements(IOError, IIOError) -classImplements(KeyboardInterrupt, IKeyboardInterrupt) -classImplements(KeyError, IKeyError) -classImplements(LookupError, ILookupError) -classImplements(MemoryError, IMemoryError) -classImplements(NameError, INameError) -classImplements(NotImplementedError, INotImplementedError) -classImplements(OSError, IOSError) -classImplements(OverflowError, IOverflowError) -classImplements(OverflowWarning, IOverflowWarning) -classImplements(ReferenceError, IReferenceError) -classImplements(RuntimeError, IRuntimeError) -classImplements(RuntimeWarning, IRuntimeWarning) -classImplements(StandardError, IStandardError) -classImplements(StopIteration, IStopIteration) -classImplements(SyntaxError, ISyntaxError) -classImplements(SyntaxWarning, ISyntaxWarning) -classImplements(SystemError, ISystemError) -classImplements(SystemExit, ISystemExit) -classImplements(TabError, ITabError) -classImplements(TypeError, ITypeError) -classImplements(UnboundLocalError, IUnboundLocalError) -classImplements(UnicodeError, IUnicodeError) -classImplements(UserWarning, IUserWarning) -classImplements(ValueError, IValueError) -classImplements(Warning, IWarning) -classImplements(ZeroDivisionError, IZeroDivisionError) - diff --git a/src/zope/interface/common/mapping.py b/src/zope/interface/common/mapping.py deleted file mode 100644 index 8779dab..0000000 --- a/src/zope/interface/common/mapping.py +++ /dev/null @@ -1,127 +0,0 @@ -############################################################################## -# -# Copyright (c) 2001, 2002 Zope Corporation 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. -# -############################################################################## -"""Mapping Interfaces - -$Id$ -""" -from zope.interface import Interface - -class IItemMapping(Interface): - """Simplest readable mapping object - """ - - def __getitem__(key): - """Get a value for a key - - A KeyError is raised if there is no value for the key. - """ - - -class IReadMapping(IItemMapping): - """Basic mapping interface - """ - - def get(key, default=None): - """Get a value for a key - - The default is returned if there is no value for the key. - """ - - def __contains__(key): - """Tell if a key exists in the mapping.""" - - -class IWriteMapping(Interface): - """Mapping methods for changing data""" - - def __delitem__(key): - """Delete a value from the mapping using the key.""" - - def __setitem__(key, value): - """Set a new item in the mapping.""" - - -class IEnumerableMapping(IReadMapping): - """Mapping objects whose items can be enumerated. - """ - - def keys(): - """Return the keys of the mapping object. - """ - - def __iter__(): - """Return an iterator for the keys of the mapping object. - """ - - def values(): - """Return the values of the mapping object. - """ - - def items(): - """Return the items of the mapping object. - """ - - def __len__(): - """Return the number of items. - """ - -class IMapping(IWriteMapping, IEnumerableMapping): - ''' Simple mapping interface ''' - -class IIterableMapping(IEnumerableMapping): - - def iterkeys(): - "iterate over keys; equivalent to __iter__" - - def itervalues(): - "iterate over values" - - def iteritems(): - "iterate over items" - -class IClonableMapping(Interface): - - def copy(): - "return copy of dict" - -class IExtendedReadMapping(IIterableMapping): - - def has_key(key): - """Tell if a key exists in the mapping; equivalent to __contains__""" - -class IExtendedWriteMapping(IWriteMapping): - - def clear(): - "delete all items" - - def update(d): - " Update D from E: for k in E.keys(): D[k] = E[k]" - - def setdefault(key, default=None): - "D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D" - - def pop(k, *args): - """remove specified key and return the corresponding value - *args may contain a single default value, or may not be supplied. - If key is not found, default is returned if given, otherwise - KeyError is raised""" - - def popitem(): - """remove and return some (key, value) pair as a - 2-tuple; but raise KeyError if mapping is empty""" - -class IFullMapping( - IExtendedReadMapping, IExtendedWriteMapping, IClonableMapping, IMapping): - ''' Full mapping interface ''' # IMapping included so tests for IMapping - # succeed with IFullMapping diff --git a/src/zope/interface/common/sequence.py b/src/zope/interface/common/sequence.py deleted file mode 100644 index 43a3d71..0000000 --- a/src/zope/interface/common/sequence.py +++ /dev/null @@ -1,152 +0,0 @@ -############################################################################## -# -# Copyright (c) 2001, 2002 Zope Corporation 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. -# -############################################################################## -"""Sequence Interfaces - -$Id$ -""" -__docformat__ = 'restructuredtext' -from zope import interface - -class IMinimalSequence(interface.Interface): - - def __getitem__(index): - """`x.__getitem__(index)` <==> `x[index]` - - Declaring this interface does not specify whether `__getitem__` - supports slice objects.""" - - def __iter__(): - """`x.__iter__()` <==> `iter(x)`""" - -class IFiniteSequence(IMinimalSequence): - - def __len__(): - """`x.__len__()` <==> `len(x)`""" - -class IReadSequence(IFiniteSequence): - """read interface shared by tuple and list""" - - def __contains__(item): - """`x.__contains__(item)` <==> `item in x`""" - - def __lt__(other): - """`x.__lt__(other)` <==> `x < other`""" - - def __le__(other): - """`x.__le__(other)` <==> `x <= other`""" - - def __eq__(other): - """`x.__eq__(other)` <==> `x == other`""" - - def __ne__(other): - """`x.__ne__(other)` <==> `x != other`""" - - def __gt__(other): - """`x.__gt__(other)` <==> `x > other`""" - - def __ge__(other): - """`x.__ge__(other)` <==> `x >= other`""" - - def __add__(other): - """`x.__add__(other)` <==> `x + other`""" - - def __mul__(n): - """`x.__mul__(n)` <==> `x * n`""" - - def __rmul__(n): - """`x.__rmul__(n)` <==> `n * x`""" - - def __getslice__(i, j): - """`x.__getslice__(i, j)` <==> `x[i:j]` - - Use of negative indices is not supported. - - Deprecated since Python 2.0 but still a part of `UserList`. - """ - -class IExtendedReadSequence(IReadSequence): - """Full read interface for lists""" - - def count(item): - """Return number of occurrences of value""" - - def index(item, *args): - """Return first index of value - - `L.index(value, [start, [stop]])` -> integer""" - -class IUniqueMemberWriteSequence(interface.Interface): - """The write contract for a sequence that may enforce unique members""" - - def __setitem__(index, item): - """`x.__setitem__(index, item)` <==> `x[index] = item` - - Declaring this interface does not specify whether `__setitem__` - supports slice objects. - """ - - def __delitem__(index): - """`x.__delitem__(index)` <==> `del x[index]` - - Declaring this interface does not specify whether `__delitem__` - supports slice objects. - """ - - def __setslice__(i, j, other): - """`x.__setslice__(i, j, other)` <==> `x[i:j]=other` - - Use of negative indices is not supported. - - Deprecated since Python 2.0 but still a part of `UserList`. - """ - - def __delslice__(i, j): - """`x.__delslice__(i, j)` <==> `del x[i:j]` - - Use of negative indices is not supported. - - Deprecated since Python 2.0 but still a part of `UserList`. - """ - def __iadd__(y): - """`x.__iadd__(y)` <==> `x += y`""" - - def append(item): - """Append item to end""" - - def insert(index, item): - """Insert item before index""" - - def pop(index=-1): - """Remove and return item at index (default last)""" - - def remove(item): - """Remove first occurrence of value""" - - def reverse(): - """Reverse *IN PLACE*""" - - def sort(cmpfunc=None): - """Stable sort *IN PLACE*; `cmpfunc(x, y)` -> -1, 0, 1""" - - def extend(iterable): - """Extend list by appending elements from the iterable""" - -class IWriteSequence(IUniqueMemberWriteSequence): - """Full write contract for sequences""" - - def __imul__(n): - """`x.__imul__(n)` <==> `x *= n`""" - -class ISequence(IReadSequence, IWriteSequence): - """Full sequence contract""" diff --git a/src/zope/interface/common/tests/__init__.py b/src/zope/interface/common/tests/__init__.py deleted file mode 100644 index b711d36..0000000 --- a/src/zope/interface/common/tests/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# -# This file is necessary to make this directory a package. diff --git a/src/zope/interface/common/tests/basemapping.py b/src/zope/interface/common/tests/basemapping.py deleted file mode 100644 index de03f54..0000000 --- a/src/zope/interface/common/tests/basemapping.py +++ /dev/null @@ -1,115 +0,0 @@ -############################################################################## -# -# Copyright (c) 2001, 2002 Zope Corporation 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. -# -############################################################################## -"""Base Mapping tests - -$Id$ -""" -from operator import __getitem__ - -def testIReadMapping(self, inst, state, absent): - for key in state: - self.assertEqual(inst[key], state[key]) - self.assertEqual(inst.get(key, None), state[key]) - self.failUnless(key in inst) - - for key in absent: - self.assertEqual(inst.get(key, None), None) - self.assertEqual(inst.get(key), None) - self.assertEqual(inst.get(key, self), self) - self.assertRaises(KeyError, __getitem__, inst, key) - - -def test_keys(self, inst, state): - # Return the keys of the mapping object - inst_keys = list(inst.keys()); inst_keys.sort() - state_keys = list(state.keys()) ; state_keys.sort() - self.assertEqual(inst_keys, state_keys) - -def test_iter(self, inst, state): - # Return the keys of the mapping object - inst_keys = list(inst); inst_keys.sort() - state_keys = list(state.keys()) ; state_keys.sort() - self.assertEqual(inst_keys, state_keys) - -def test_values(self, inst, state): - # Return the values of the mapping object - inst_values = list(inst.values()); inst_values.sort() - state_values = list(state.values()) ; state_values.sort() - self.assertEqual(inst_values, state_values) - -def test_items(self, inst, state): - # Return the items of the mapping object - inst_items = list(inst.items()); inst_items.sort() - state_items = list(state.items()) ; state_items.sort() - self.assertEqual(inst_items, state_items) - -def test___len__(self, inst, state): - # Return the number of items - self.assertEqual(len(inst), len(state)) - -def testIEnumerableMapping(self, inst, state): - test_keys(self, inst, state) - test_items(self, inst, state) - test_values(self, inst, state) - test___len__(self, inst, state) - - -class BaseTestIReadMapping(object): - def testIReadMapping(self): - inst = self._IReadMapping__sample() - state = self._IReadMapping__stateDict() - absent = self._IReadMapping__absentKeys() - testIReadMapping(self, inst, state, absent) - - -class BaseTestIEnumerableMapping(BaseTestIReadMapping): - # Mapping objects whose items can be enumerated - def test_keys(self): - # Return the keys of the mapping object - inst = self._IEnumerableMapping__sample() - state = self._IEnumerableMapping__stateDict() - test_keys(self, inst, state) - - def test_values(self): - # Return the values of the mapping object - inst = self._IEnumerableMapping__sample() - state = self._IEnumerableMapping__stateDict() - test_values(self, inst, state) - - def test_values(self): - # Return the values of the mapping object - inst = self._IEnumerableMapping__sample() - state = self._IEnumerableMapping__stateDict() - test_iter(self, inst, state) - - def test_items(self): - # Return the items of the mapping object - inst = self._IEnumerableMapping__sample() - state = self._IEnumerableMapping__stateDict() - test_items(self, inst, state) - - def test___len__(self): - # Return the number of items - inst = self._IEnumerableMapping__sample() - state = self._IEnumerableMapping__stateDict() - test___len__(self, inst, state) - - def _IReadMapping__stateDict(self): - return self._IEnumerableMapping__stateDict() - - def _IReadMapping__sample(self): - return self._IEnumerableMapping__sample() - - def _IReadMapping__absentKeys(self): - return self._IEnumerableMapping__absentKeys() diff --git a/src/zope/interface/common/tests/test_idatetime.py b/src/zope/interface/common/tests/test_idatetime.py deleted file mode 100644 index f84316a..0000000 --- a/src/zope/interface/common/tests/test_idatetime.py +++ /dev/null @@ -1,49 +0,0 @@ -############################################################################## -# -# Copyright (c) 2003 Zope Corporation 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 for datetime interfaces - -$Id$ -""" - -import unittest - -from zope.interface.verify import verifyObject, verifyClass -from zope.interface.common.idatetime import ITimeDelta, ITimeDeltaClass -from zope.interface.common.idatetime import IDate, IDateClass -from zope.interface.common.idatetime import IDateTime, IDateTimeClass -from zope.interface.common.idatetime import ITime, ITimeClass, ITZInfo -from datetime import timedelta, date, datetime, time, tzinfo - -class TestDateTimeInterfaces(unittest.TestCase): - - def test_interfaces(self): - verifyObject(ITimeDelta, timedelta(minutes=20)) - verifyObject(IDate, date(2000, 1, 2)) - verifyObject(IDateTime, datetime(2000, 1, 2, 10, 20)) - verifyObject(ITime, time(20, 30, 15, 1234)) - verifyObject(ITZInfo, tzinfo()) - verifyClass(ITimeDeltaClass, timedelta) - verifyClass(IDateClass, date) - verifyClass(IDateTimeClass, datetime) - verifyClass(ITimeClass, time) - - -def test_suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestDateTimeInterfaces)) - return suite - - -if __name__ == '__main__': - unittest.main() diff --git a/src/zope/interface/declarations.py b/src/zope/interface/declarations.py deleted file mode 100644 index 1408df4..0000000 --- a/src/zope/interface/declarations.py +++ /dev/null @@ -1,1378 +0,0 @@ -############################################################################## -# Copyright (c) 2003 Zope Corporation 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. -############################################################################## -"""Implementation of interface declarations - -There are three flavors of declarations: - - - Declarations are used to simply name declared interfaces. - - - ImplementsDeclarations are used to express the interfaces that a - class implements (that instances of the class provides). - - Implements specifications support inheriting interfaces. - - - ProvidesDeclarations are used to express interfaces directly - provided by objects. - - -$Id$ -""" -__docformat__ = 'restructuredtext' - -import sys -import types -import weakref -from zope.interface.interface import InterfaceClass, Specification -from ro import mergeOrderings, ro -import exceptions -from types import ClassType -from zope.interface.advice import addClassAdvisor - -# Registry of class-implementation specifications -BuiltinImplementationSpecifications = {} - -class Declaration(Specification): - """Interface declarations""" - - def __init__(self, *interfaces): - Specification.__init__(self, _normalizeargs(interfaces)) - - def changed(self): - Specification.changed(self) - try: - del self._v_attrs - except AttributeError: - pass - - def __contains__(self, interface): - """Test whether an interface is in the specification - - for example: - - >>> from zope.interface import Interface - >>> class I1(Interface): pass - ... - >>> class I2(I1): pass - ... - >>> class I3(Interface): pass - ... - >>> class I4(I3): pass - ... - >>> spec = Declaration(I2, I3) - >>> spec = Declaration(I4, spec) - >>> int(I1 in spec) - 0 - >>> int(I2 in spec) - 1 - >>> int(I3 in spec) - 1 - >>> int(I4 in spec) - 1 - """ - return self.extends(interface) and interface in self.interfaces() - - def __iter__(self): - """Return an iterator for the interfaces in the specification - - for example: - - >>> from zope.interface import Interface - >>> class I1(Interface): pass - ... - >>> class I2(I1): pass - ... - >>> class I3(Interface): pass - ... - >>> class I4(I3): pass - ... - >>> spec = Declaration(I2, I3) - >>> spec = Declaration(I4, spec) - >>> i = iter(spec) - >>> i.next().getName() - 'I4' - >>> i.next().getName() - 'I2' - >>> i.next().getName() - 'I3' - >>> list(i) - [] - """ - return self.interfaces() - - def flattened(self): - """Return an iterator of all included and extended interfaces - - for example: - - >>> from zope.interface import Interface - >>> class I1(Interface): pass - ... - >>> class I2(I1): pass - ... - >>> class I3(Interface): pass - ... - >>> class I4(I3): pass - ... - >>> spec = Declaration(I2, I3) - >>> spec = Declaration(I4, spec) - >>> i = spec.flattened() - >>> i.next().getName() - 'I4' - >>> i.next().getName() - 'I2' - >>> i.next().getName() - 'I1' - >>> i.next().getName() - 'I3' - >>> i.next().getName() - 'Interface' - >>> list(i) - [] - - """ - return iter(self.__iro__) - - def __sub__(self, other): - """Remove interfaces from a specification - - Examples: - - >>> from zope.interface import Interface - >>> class I1(Interface): pass - ... - >>> class I2(I1): pass - ... - >>> class I3(Interface): pass - ... - >>> class I4(I3): pass - ... - >>> spec = Declaration() - >>> [iface.getName() for iface in spec] - [] - >>> spec -= I1 - >>> [iface.getName() for iface in spec] - [] - >>> spec -= Declaration(I1, I2) - >>> [iface.getName() for iface in spec] - [] - >>> spec = Declaration(I2, I4) - >>> [iface.getName() for iface in spec] - ['I2', 'I4'] - >>> [iface.getName() for iface in spec - I4] - ['I2'] - >>> [iface.getName() for iface in spec - I1] - ['I4'] - >>> [iface.getName() for iface - ... in spec - Declaration(I3, I4)] - ['I2'] - - """ - - return Declaration( - *[i for i in self.interfaces() - if not [j for j in other.interfaces() - if i.extends(j, 0)] - ] - ) - - def __add__(self, other): - """Add two specifications or a specification and an interface - - Examples: - - >>> from zope.interface import Interface - >>> class I1(Interface): pass - ... - >>> class I2(I1): pass - ... - >>> class I3(Interface): pass - ... - >>> class I4(I3): pass - ... - >>> spec = Declaration() - >>> [iface.getName() for iface in spec] - [] - >>> [iface.getName() for iface in spec+I1] - ['I1'] - >>> [iface.getName() for iface in I1+spec] - ['I1'] - >>> spec2 = spec - >>> spec += I1 - >>> [iface.getName() for iface in spec] - ['I1'] - >>> [iface.getName() for iface in spec2] - [] - >>> spec2 += Declaration(I3, I4) - >>> [iface.getName() for iface in spec2] - ['I3', 'I4'] - >>> [iface.getName() for iface in spec+spec2] - ['I1', 'I3', 'I4'] - >>> [iface.getName() for iface in spec2+spec] - ['I3', 'I4', 'I1'] - - """ - - seen = {} - result = [] - for i in self.interfaces(): - if i not in seen: - seen[i] = 1 - result.append(i) - for i in other.interfaces(): - if i not in seen: - seen[i] = 1 - result.append(i) - - return Declaration(*result) - - __radd__ = __add__ - - def __nonzero__(self): - """Test whether there are any interfaces in a specification. - - >>> from zope.interface import Interface - >>> class I1(Interface): pass - ... - >>> spec = Declaration(I1) - >>> int(bool(spec)) - 1 - >>> spec = Declaration() - >>> int(bool(spec)) - 0 - """ - return bool(self.__iro__) - - -############################################################################## -# -# Implementation specifications -# -# These specify interfaces implemented by instances of classes - -class Implements(Declaration): - - # class whose specification should be used as additional base - inherit = None - - # interfaces actually declared for a class - declared = () - - __name__ = '?' - - def __repr__(self): - return '<implementedBy %s>' % (self.__name__) - - -def implementedByFallback(cls): - """Return the interfaces implemented for a class' instances - - The value returned is an IDeclaration. - - for example: - - >>> from zope.interface import Interface - >>> class I1(Interface): pass - ... - >>> class I2(I1): pass - ... - >>> class I3(Interface): pass - ... - >>> class I4(I3): pass - ... - >>> class C1(object): - ... implements(I2) - >>> class C2(C1): - ... implements(I3) - >>> [i.getName() for i in implementedBy(C2)] - ['I3', 'I2'] - - Really, any object should be able to receive a successful answer, even - an instance: - - >>> class Callable(object): - ... def __call__(self): - ... return self - - >>> implementedBy(Callable()) - <implementedBy zope.interface.declarations.?> - - Note that the name of the spec ends with a '?', because the `Callable` - instance does not have a `__name__` attribute. - """ - # This also manages storage of implementation specifications - - try: - spec = cls.__dict__.get('__implemented__') - except AttributeError: - - # we can't get the class dict. This is probably due to a - # security proxy. If this is the case, then probably no - # descriptor was installed for the class. - - # We don't want to depend directly on zope.security in - # zope.interface, but we'll try to make reasonable - # accommodations in an indirect way. - - # We'll check to see if there's an implements: - - spec = getattr(cls, '__implemented__', None) - if spec is None: - # There's no spec stred in the class. Maybe its a builtin: - spec = BuiltinImplementationSpecifications.get(cls) - if spec is not None: - return spec - return _empty - - if spec.__class__ == Implements: - # we defaulted to _empty or there was a spec. Good enough. - # Return it. - return spec - - # TODO: need old style __implements__ compatibility? - # Hm, there's an __implemented__, but it's not a spec. Must be - # an old-style declaration. Just compute a spec for it - return Declaration(*_normalizeargs((spec, ))) - - if isinstance(spec, Implements): - return spec - - if spec is None: - spec = BuiltinImplementationSpecifications.get(cls) - if spec is not None: - return spec - - # TODO: need old style __implements__ compatibility? - if spec is not None: - # old-style __implemented__ = foo declaration - spec = (spec, ) # tuplefy, as it might be just an int - spec = Implements(*_normalizeargs(spec)) - spec.inherit = None # old-style implies no inherit - del cls.__implemented__ # get rid of the old-style declaration - else: - try: - bases = cls.__bases__ - except AttributeError: - if not callable(cls): - raise TypeError("ImplementedBy called for non-factory", cls) - bases = () - - spec = Implements(*[implementedBy(c) for c in bases]) - spec.inherit = cls - - spec.__name__ = (getattr(cls, '__module__', '?') or '?') + \ - '.' + (getattr(cls, '__name__', '?') or '?') - - try: - cls.__implemented__ = spec - if not hasattr(cls, '__providedBy__'): - cls.__providedBy__ = objectSpecificationDescriptor - - if (isinstance(cls, DescriptorAwareMetaClasses) - and - '__provides__' not in cls.__dict__): - # Make sure we get a __provides__ descriptor - cls.__provides__ = ClassProvides( - cls, - getattr(cls, '__class__', type(cls)), - ) - - except TypeError: - if not isinstance(cls, type): - raise TypeError("ImplementedBy called for non-type", cls) - BuiltinImplementationSpecifications[cls] = spec - - return spec - -implementedBy = implementedByFallback - -def classImplementsOnly(cls, *interfaces): - """Declare the only interfaces implemented by instances of a class - - The arguments after the class are one or more interfaces or interface - specifications (``IDeclaration`` objects). - - The interfaces given (including the interfaces in the specifications) - replace any previous declarations. - - Consider the following example: - - >>> from zope.interface import Interface - >>> class I1(Interface): pass - ... - >>> class I2(Interface): pass - ... - >>> class I3(Interface): pass - ... - >>> class I4(Interface): pass - ... - >>> class A(object): - ... implements(I3) - >>> class B(object): - ... implements(I4) - >>> class C(A, B): - ... pass - >>> classImplementsOnly(C, I1, I2) - >>> [i.getName() for i in implementedBy(C)] - ['I1', 'I2'] - - Instances of ``C`` provide only ``I1``, ``I2``, and regardless of - whatever interfaces instances of ``A`` and ``B`` implement. - """ - spec = implementedBy(cls) - spec.declared = () - spec.inherit = None - classImplements(cls, *interfaces) - -def classImplements(cls, *interfaces): - """Declare additional interfaces implemented for instances of a class - - The arguments after the class are one or more interfaces or - interface specifications (``IDeclaration`` objects). - - The interfaces given (including the interfaces in the specifications) - are added to any interfaces previously declared. - - Consider the following example: - - >>> from zope.interface import Interface - >>> class I1(Interface): pass - ... - >>> class I2(Interface): pass - ... - >>> class I3(Interface): pass - ... - >>> class I4(Interface): pass - ... - >>> class I5(Interface): pass - ... - >>> class A(object): - ... implements(I3) - >>> class B(object): - ... implements(I4) - >>> class C(A, B): - ... pass - >>> classImplements(C, I1, I2) - >>> [i.getName() for i in implementedBy(C)] - ['I1', 'I2', 'I3', 'I4'] - >>> classImplements(C, I5) - >>> [i.getName() for i in implementedBy(C)] - ['I1', 'I2', 'I5', 'I3', 'I4'] - - Instances of ``C`` provide ``I1``, ``I2``, ``I5``, and whatever - interfaces instances of ``A`` and ``B`` provide. - """ - - spec = implementedBy(cls) - spec.declared += tuple(_normalizeargs(interfaces)) - - # compute the bases - bases = [] - seen = {} - for b in spec.declared: - if b not in seen: - seen[b] = 1 - bases.append(b) - - if spec.inherit is not None: - - for c in spec.inherit.__bases__: - b = implementedBy(c) - if b not in seen: - seen[b] = 1 - bases.append(b) - - spec.__bases__ = tuple(bases) - -def _implements_advice(cls): - interfaces, classImplements = cls.__dict__['__implements_advice_data__'] - del cls.__implements_advice_data__ - classImplements(cls, *interfaces) - return cls - - -class implementer: - - def __init__(self, *interfaces): - self.interfaces = interfaces - - def __call__(self, ob): - if isinstance(ob, DescriptorAwareMetaClasses): - raise TypeError("Can't use implementer with classes. Use one of " - "the class-declaration functions instead." - ) - spec = Implements(*self.interfaces) - try: - ob.__implemented__ = spec - except AttributeError: - raise TypeError("Can't declare implements", ob) - return ob - -def _implements(name, interfaces, classImplements): - frame = sys._getframe(2) - locals = frame.f_locals - - # Try to make sure we were called from a class def. In 2.2.0 we can't - # check for __module__ since it doesn't seem to be added to the locals - # until later on. - if (locals is frame.f_globals) or ( - ('__module__' not in locals) and sys.version_info[:3] > (2, 2, 0)): - raise TypeError(name+" can be used only from a class definition.") - - if '__implements_advice_data__' in locals: - raise TypeError(name+" can be used only once in a class definition.") - - locals['__implements_advice_data__'] = interfaces, classImplements - addClassAdvisor(_implements_advice, depth=3) - -def implements(*interfaces): - """Declare interfaces implemented by instances of a class - - This function is called in a class definition. - - The arguments are one or more interfaces or interface - specifications (IDeclaration objects). - - The interfaces given (including the interfaces in the - specifications) are added to any interfaces previously - declared. - - Previous declarations include declarations for base classes - unless implementsOnly was used. - - This function is provided for convenience. It provides a more - convenient way to call classImplements. For example:: - - implements(I1) - - is equivalent to calling:: - - classImplements(C, I1) - - after the class has been created. - - Consider the following example:: - - - >>> from zope.interface import Interface - >>> class IA1(Interface): pass - ... - >>> class IA2(Interface): pass - ... - >>> class IB(Interface): pass - ... - >>> class IC(Interface): pass - ... - >>> class A(object): implements(IA1, IA2) - ... - >>> class B(object): implements(IB) - ... - - >>> class C(A, B): - ... implements(IC) - - >>> ob = C() - >>> int(IA1 in providedBy(ob)) - 1 - >>> int(IA2 in providedBy(ob)) - 1 - >>> int(IB in providedBy(ob)) - 1 - >>> int(IC in providedBy(ob)) - 1 - - Instances of ``C`` implement ``I1``, ``I2``, and whatever interfaces - instances of ``A`` and ``B`` implement. - - """ - _implements("implements", interfaces, classImplements) - -def implementsOnly(*interfaces): - """Declare the only interfaces implemented by instances of a class - - This function is called in a class definition. - - The arguments are one or more interfaces or interface - specifications (IDeclaration objects). - - Previous declarations including declarations for base classes - are overridden. - - This function is provided for convenience. It provides a more - convenient way to call classImplementsOnly. For example:: - - implementsOnly(I1) - - is equivalent to calling:: - - classImplementsOnly(I1) - - after the class has been created. - - Consider the following example:: - - >>> from zope.interface import Interface - >>> class IA1(Interface): pass - ... - >>> class IA2(Interface): pass - ... - >>> class IB(Interface): pass - ... - >>> class IC(Interface): pass - ... - >>> class A(object): implements(IA1, IA2) - ... - >>> class B(object): implements(IB) - ... - - >>> class C(A, B): - ... implementsOnly(IC) - - >>> ob = C() - >>> int(IA1 in providedBy(ob)) - 0 - >>> int(IA2 in providedBy(ob)) - 0 - >>> int(IB in providedBy(ob)) - 0 - >>> int(IC in providedBy(ob)) - 1 - - - Instances of ``C`` implement ``IC``, regardless of what - instances of ``A`` and ``B`` implement. - - """ - _implements("implementsOnly", interfaces, classImplementsOnly) - -############################################################################## -# -# Instance declarations - -class Provides(Declaration): # Really named ProvidesClass - """Implement __provides__, the instance-specific specification - - When an object is pickled, we pickle the interfaces that it implements. - """ - - def __init__(self, cls, *interfaces): - self.__args = (cls, ) + interfaces - self._cls = cls - Declaration.__init__(self, *(interfaces + (implementedBy(cls), ))) - - def __reduce__(self): - return Provides, self.__args - - __module__ = 'zope.interface' - - def __get__(self, inst, cls): - """Make sure that a class __provides__ doesn't leak to an instance - - For example: - - >>> from zope.interface import Interface - >>> class IFooFactory(Interface): pass - ... - - >>> class C(object): - ... pass - - >>> C.__provides__ = ProvidesClass(C, IFooFactory) - >>> [i.getName() for i in C.__provides__] - ['IFooFactory'] - >>> getattr(C(), '__provides__', 0) - 0 - - """ - if inst is None and cls is self._cls: - # We were accessed through a class, so we are the class' - # provides spec. Just return this object, but only if we are - # being called on the same class that we were defined for: - return self - - raise AttributeError('__provides__') - -ProvidesClass = Provides - -# Registry of instance declarations -# This is a memory optimization to allow objects to share specifications. -InstanceDeclarations = weakref.WeakValueDictionary() - -def Provides(*interfaces): - """Cache instance declarations - - Instance declarations are shared among instances that have the same - declaration. The declarations are cached in a weak value dictionary. - - (Note that, in the examples below, we are going to make assertions about - the size of the weakvalue dictionary. For the assertions to be - meaningful, we need to force garbage collection to make sure garbage - objects are, indeed, removed from the system. Depending on how Python - is run, we may need to make multiple calls to be sure. We provide a - collect function to help with this: - - >>> import gc - >>> def collect(): - ... for i in range(4): - ... gc.collect() - - ) - - >>> collect() - >>> before = len(InstanceDeclarations) - - >>> class C(object): - ... pass - - >>> from zope.interface import Interface - >>> class I(Interface): - ... pass - - >>> c1 = C() - >>> c2 = C() - - >>> len(InstanceDeclarations) == before - 1 - - >>> directlyProvides(c1, I) - >>> len(InstanceDeclarations) == before + 1 - 1 - - >>> directlyProvides(c2, I) - >>> len(InstanceDeclarations) == before + 1 - 1 - - >>> del c1 - >>> collect() - >>> len(InstanceDeclarations) == before + 1 - 1 - - >>> del c2 - >>> collect() - >>> len(InstanceDeclarations) == before - 1 - """ - - spec = InstanceDeclarations.get(interfaces) - if spec is None: - spec = ProvidesClass(*interfaces) - InstanceDeclarations[interfaces] = spec - - return spec -Provides.__safe_for_unpickling__ = True - - -DescriptorAwareMetaClasses = ClassType, type -def directlyProvides(object, *interfaces): - """Declare interfaces declared directly for an object - - The arguments after the object are one or more interfaces or interface - specifications (``IDeclaration`` objects). - - The interfaces given (including the interfaces in the specifications) - replace interfaces previously declared for the object. - - Consider the following example: - - >>> from zope.interface import Interface - >>> class I1(Interface): pass - ... - >>> class I2(Interface): pass - ... - >>> class IA1(Interface): pass - ... - >>> class IA2(Interface): pass - ... - >>> class IB(Interface): pass - ... - >>> class IC(Interface): pass - ... - >>> class A(object): implements(IA1, IA2) - ... - >>> class B(object): implements(IB) - ... - - >>> class C(A, B): - ... implements(IC) - - >>> ob = C() - >>> directlyProvides(ob, I1, I2) - >>> int(I1 in providedBy(ob)) - 1 - >>> int(I2 in providedBy(ob)) - 1 - >>> int(IA1 in providedBy(ob)) - 1 - >>> int(IA2 in providedBy(ob)) - 1 - >>> int(IB in providedBy(ob)) - 1 - >>> int(IC in providedBy(ob)) - 1 - - The object, ``ob`` provides ``I1``, ``I2``, and whatever interfaces - instances have been declared for instances of ``C``. - - To remove directly provided interfaces, use ``directlyProvidedBy`` and - subtract the unwanted interfaces. For example: - - >>> directlyProvides(ob, directlyProvidedBy(ob)-I2) - >>> int(I1 in providedBy(ob)) - 1 - >>> int(I2 in providedBy(ob)) - 0 - - removes I2 from the interfaces directly provided by ``ob``. The object, - ``ob`` no longer directly provides ``I2``, although it might still - provide ``I2`` if it's class implements ``I2``. - - To add directly provided interfaces, use ``directlyProvidedBy`` and - include additional interfaces. For example: - - >>> int(I2 in providedBy(ob)) - 0 - >>> directlyProvides(ob, directlyProvidedBy(ob), I2) - - adds ``I2`` to the interfaces directly provided by ob:: - - >>> int(I2 in providedBy(ob)) - 1 - - """ - - # We need to avoid setting this attribute on meta classes that - # don't support descriptors. - # We can do away with this check when we get rid of the old EC - cls = getattr(object, '__class__', None) - if cls is not None and getattr(cls, '__class__', None) is cls: - # It's a meta class (well, at least it it could be an extension class) - if not isinstance(object, DescriptorAwareMetaClasses): - raise TypeError("Attempt to make an interface declaration on a " - "non-descriptor-aware class") - - interfaces = _normalizeargs(interfaces) - if cls is None: - cls = type(object) - - issub = False - for damc in DescriptorAwareMetaClasses: - if issubclass(cls, damc): - issub = True - break - if issub: - # we have a class or type. We'll use a special descriptor - # that provides some extra caching - object.__provides__ = ClassProvides(object, cls, *interfaces) - else: - object.__provides__ = Provides(cls, *interfaces) - - -def alsoProvides(object, *interfaces): - """Declare interfaces declared directly for an object - - The arguments after the object are one or more interfaces or interface - specifications (``IDeclaration`` objects). - - The interfaces given (including the interfaces in the specifications) are - added to the interfaces previously declared for the object. - - Consider the following example: - - >>> from zope.interface import Interface - >>> class I1(Interface): pass - ... - >>> class I2(Interface): pass - ... - >>> class IA1(Interface): pass - ... - >>> class IA2(Interface): pass - ... - >>> class IB(Interface): pass - ... - >>> class IC(Interface): pass - ... - >>> class A(object): implements(IA1, IA2) - ... - >>> class B(object): implements(IB) - ... - - >>> class C(A, B): - ... implements(IC) - - >>> ob = C() - >>> directlyProvides(ob, I1) - >>> int(I1 in providedBy(ob)) - 1 - >>> int(I2 in providedBy(ob)) - 0 - >>> int(IA1 in providedBy(ob)) - 1 - >>> int(IA2 in providedBy(ob)) - 1 - >>> int(IB in providedBy(ob)) - 1 - >>> int(IC in providedBy(ob)) - 1 - - >>> alsoProvides(ob, I2) - >>> int(I1 in providedBy(ob)) - 1 - >>> int(I2 in providedBy(ob)) - 1 - >>> int(IA1 in providedBy(ob)) - 1 - >>> int(IA2 in providedBy(ob)) - 1 - >>> int(IB in providedBy(ob)) - 1 - >>> int(IC in providedBy(ob)) - 1 - - The object, ``ob`` provides ``I1``, ``I2``, and whatever interfaces - instances have been declared for instances of ``C``. Notice that the - alsoProvides just extends the provided interfaces. - """ - directlyProvides(object, directlyProvidedBy(object), *interfaces) - -class ClassProvidesBasePy(object): - - def __get__(self, inst, cls): - if cls is self._cls: - # We only work if called on the class we were defined for - - if inst is None: - # We were accessed through a class, so we are the class' - # provides spec. Just return this object as is: - return self - - return self._implements - - raise AttributeError('__provides__') - -ClassProvidesBase = ClassProvidesBasePy - -# Try to get C base: -try: - import _zope_interface_coptimizations -except ImportError: - pass -else: - from _zope_interface_coptimizations import ClassProvidesBase - - -class ClassProvides(Declaration, ClassProvidesBase): - """Special descriptor for class __provides__ - - The descriptor caches the implementedBy info, so that - we can get declarations for objects without instance-specific - interfaces a bit quicker. - - For example: - - >>> from zope.interface import Interface - >>> class IFooFactory(Interface): - ... pass - >>> class IFoo(Interface): - ... pass - >>> class C(object): - ... implements(IFoo) - ... classProvides(IFooFactory) - >>> [i.getName() for i in C.__provides__] - ['IFooFactory'] - - >>> [i.getName() for i in C().__provides__] - ['IFoo'] - """ - - def __init__(self, cls, metacls, *interfaces): - self._cls = cls - self._implements = implementedBy(cls) - self.__args = (cls, metacls, ) + interfaces - Declaration.__init__(self, *(interfaces + (implementedBy(metacls), ))) - - def __reduce__(self): - return self.__class__, self.__args - - # Copy base-class method for speed - __get__ = ClassProvidesBase.__get__ - -def directlyProvidedBy(object): - """Return the interfaces directly provided by the given object - - The value returned is an ``IDeclaration``. - """ - provides = getattr(object, "__provides__", None) - if (provides is None # no spec - or - # We might have gotten the implements spec, as an - # optimization. If so, it's like having only one base, that we - # lop off to exclude class-supplied declarations: - isinstance(provides, Implements) - ): - return _empty - - # Strip off the class part of the spec: - return Declaration(provides.__bases__[:-1]) - -def classProvides(*interfaces): - """Declare interfaces provided directly by a class - - This function is called in a class definition. - - The arguments are one or more interfaces or interface specifications - (``IDeclaration`` objects). - - The given interfaces (including the interfaces in the specifications) - are used to create the class's direct-object interface specification. - An error will be raised if the module class has an direct interface - specification. In other words, it is an error to call this function more - than once in a class definition. - - Note that the given interfaces have nothing to do with the interfaces - implemented by instances of the class. - - This function is provided for convenience. It provides a more convenient - way to call directlyProvidedByProvides for a class. For example:: - - classProvides(I1) - - is equivalent to calling:: - - directlyProvides(theclass, I1) - - after the class has been created. - - For example: - - >>> from zope.interface import Interface - >>> class IFoo(Interface): pass - ... - >>> class IFooFactory(Interface): pass - ... - >>> class C(object): - ... implements(IFoo) - ... classProvides(IFooFactory) - >>> [i.getName() for i in C.__providedBy__] - ['IFooFactory'] - >>> [i.getName() for i in C().__providedBy__] - ['IFoo'] - - if equivalent to: - - >>> from zope.interface import Interface - >>> class IFoo(Interface): pass - ... - >>> class IFooFactory(Interface): pass - ... - >>> class C(object): - ... implements(IFoo) - >>> directlyProvides(C, IFooFactory) - >>> [i.getName() for i in C.__providedBy__] - ['IFooFactory'] - >>> [i.getName() for i in C().__providedBy__] - ['IFoo'] - """ - frame = sys._getframe(1) - locals = frame.f_locals - - # Try to make sure we were called from a class def - if (locals is frame.f_globals) or ('__module__' not in locals): - raise TypeError(name+" can be used only from a class definition.") - - if '__provides__' in locals: - raise TypeError( - "classProvides can only be used once in a class definition.") - - locals["__provides__"] = _normalizeargs(interfaces) - - addClassAdvisor(_classProvides_advice, depth=2) - -def _classProvides_advice(cls): - interfaces = cls.__dict__['__provides__'] - del cls.__provides__ - directlyProvides(cls, *interfaces) - return cls - -def moduleProvides(*interfaces): - """Declare interfaces provided by a module - - This function is used in a module definition. - - The arguments are one or more interfaces or interface specifications - (``IDeclaration`` objects). - - The given interfaces (including the interfaces in the specifications) are - used to create the module's direct-object interface specification. An - error will be raised if the module already has an interface specification. - In other words, it is an error to call this function more than once in a - module definition. - - This function is provided for convenience. It provides a more convenient - way to call directlyProvides. For example:: - - moduleImplements(I1) - - is equivalent to:: - - directlyProvides(sys.modules[__name__], I1) - """ - frame = sys._getframe(1) - locals = frame.f_locals - - # Try to make sure we were called from a class def - if (locals is not frame.f_globals) or ('__name__' not in locals): - raise TypeError( - "moduleProvides can only be used from a module definition.") - - if '__provides__' in locals: - raise TypeError( - "moduleProvides can only be used once in a module definition.") - - module = sys.modules[__name__] - - locals["__provides__"] = Provides(type(module), - *_normalizeargs(interfaces)) - -############################################################################## -# -# Declaration querying support - -def ObjectSpecification(direct, cls): - """Provide object specifications - - These combine information for the object and for it's classes. - - For example: - - >>> from zope.interface import Interface - >>> class I1(Interface): pass - ... - >>> class I2(Interface): pass - ... - >>> class I3(Interface): pass - ... - >>> class I31(I3): pass - ... - >>> class I4(Interface): pass - ... - >>> class I5(Interface): pass - ... - >>> class A(object): implements(I1) - ... - >>> class B(object): __implemented__ = I2 - ... - >>> class C(A, B): implements(I31) - ... - >>> c = C() - >>> directlyProvides(c, I4) - >>> [i.getName() for i in providedBy(c)] - ['I4', 'I31', 'I1', 'I2'] - >>> [i.getName() for i in providedBy(c).flattened()] - ['I4', 'I31', 'I3', 'I1', 'I2', 'Interface'] - >>> int(I1 in providedBy(c)) - 1 - >>> int(I3 in providedBy(c)) - 0 - >>> int(providedBy(c).extends(I3)) - 1 - >>> int(providedBy(c).extends(I31)) - 1 - >>> int(providedBy(c).extends(I5)) - 0 - >>> class COnly(A, B): implementsOnly(I31) - ... - >>> class D(COnly): implements(I5) - ... - >>> c = D() - >>> directlyProvides(c, I4) - >>> [i.getName() for i in providedBy(c)] - ['I4', 'I5', 'I31'] - >>> [i.getName() for i in providedBy(c).flattened()] - ['I4', 'I5', 'I31', 'I3', 'Interface'] - >>> int(I1 in providedBy(c)) - 0 - >>> int(I3 in providedBy(c)) - 0 - >>> int(providedBy(c).extends(I3)) - 1 - >>> int(providedBy(c).extends(I1)) - 0 - >>> int(providedBy(c).extends(I31)) - 1 - >>> int(providedBy(c).extends(I5)) - 1 - - nonzero: - - >>> from zope.interface import Interface - >>> class I1(Interface): - ... pass - >>> class I2(Interface): - ... pass - >>> class C(object): - ... implements(I1) - >>> c = C() - >>> int(bool(providedBy(c))) - 1 - >>> directlyProvides(c, I2) - >>> int(bool(providedBy(c))) - 1 - >>> class C(object): - ... pass - >>> c = C() - >>> int(bool(providedBy(c))) - 0 - >>> directlyProvides(c, I2) - >>> int(bool(providedBy(c))) - 1 - """ - - return Provides(cls, direct) - -def getObjectSpecification(ob): - - provides = getattr(ob, '__provides__', None) - if provides is not None: - return provides - - try: - cls = ob.__class__ - except AttributeError: - # We can't get the class, so just consider provides - return _empty - - return implementedBy(cls) - -def providedBy(ob): - - # Here we have either a special object, an old-style declaration - # or a descriptor - - # Try to get __providedBy__ - try: - r = ob.__providedBy__ - except AttributeError: - # Not set yet. Fall back to lower-level thing that computes it - return getObjectSpecification(ob) - - try: - # We might have gotten a descriptor from an instance of a - # class (like an ExtensionClass) that doesn't support - # descriptors. We'll make sure we got one by trying to get - # the only attribute, which all specs have. - r.extends - - except AttributeError: - - # The object's class doesn't understand descriptors. - # Sigh. We need to get an object descriptor, but we have to be - # careful. We want to use the instance's __provides__, if - # there is one, but only if it didn't come from the class. - - try: - r = ob.__provides__ - except AttributeError: - # No __provides__, so just fall back to implementedBy - return implementedBy(ob.__class__) - - # We need to make sure we got the __provides__ from the - # instance. We'll do this by making sure we don't get the same - # thing from the class: - - try: - cp = ob.__class__.__provides__ - except AttributeError: - # The ob doesn't have a class or the class has no - # provides, assume we're done: - return r - - if r is cp: - # Oops, we got the provides from the class. This means - # the object doesn't have it's own. We should use implementedBy - return implementedBy(ob.__class__) - - return r - -class ObjectSpecificationDescriptorPy(object): - """Implement the `__providedBy__` attribute - - The `__providedBy__` attribute computes the interfaces peovided by - an object. - """ - - def __get__(self, inst, cls): - """Get an object specification for an object - - For example: - - >>> from zope.interface import Interface - >>> class IFoo(Interface): pass - ... - >>> class IFooFactory(Interface): pass - ... - >>> class C(object): - ... implements(IFoo) - ... classProvides(IFooFactory) - >>> [i.getName() for i in C.__providedBy__] - ['IFooFactory'] - >>> [i.getName() for i in C().__providedBy__] - ['IFoo'] - - """ - - # Get an ObjectSpecification bound to either an instance or a class, - # depending on how we were accessed. - - if inst is None: - return getObjectSpecification(cls) - - provides = getattr(inst, '__provides__', None) - if provides is not None: - return provides - - return implementedBy(cls) - -ObjectSpecificationDescriptor = ObjectSpecificationDescriptorPy - -############################################################################## - -def _normalizeargs(sequence, output = None): - """Normalize declaration arguments - - Normalization arguments might contain Declarions, tuples, or single - interfaces. - - Anything but individial interfaces or implements specs will be expanded. - """ - if output is None: - output = [] - - cls = sequence.__class__ - if InterfaceClass in cls.__mro__ or Implements in cls.__mro__: - output.append(sequence) - else: - for v in sequence: - _normalizeargs(v, output) - - return output - -_empty = Declaration() - -try: - import _zope_interface_coptimizations -except ImportError: - pass -else: - from _zope_interface_coptimizations import implementedBy, providedBy - from _zope_interface_coptimizations import getObjectSpecification - from _zope_interface_coptimizations import ObjectSpecificationDescriptor - -objectSpecificationDescriptor = ObjectSpecificationDescriptor() diff --git a/src/zope/interface/document.py b/src/zope/interface/document.py deleted file mode 100644 index 9f88f4f..0000000 --- a/src/zope/interface/document.py +++ /dev/null @@ -1,107 +0,0 @@ -############################################################################## -# -# Copyright (c) 2001, 2002 Zope Corporation 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. -# -############################################################################## -""" Pretty-Print an Interface object as structured text (Yum) - -This module provides a function, asStructuredText, for rendering an -interface as structured text. - -$Id$ -""" -import zope.interface - -def asStructuredText(I, munge=0): - """ Output structured text format. Note, this will whack any existing - 'structured' format of the text. """ - - r = [I.getName()] - outp = r.append - level = 1 - - if I.getDoc(): - outp(_justify_and_indent(_trim_doc_string(I.getDoc()), level)) - - bases = [base - for base in I.__bases__ - if base is not zope.interface.Interface - ] - if bases: - outp(_justify_and_indent("This interface extends:", level, munge)) - level += 1 - for b in bases: - item = "o %s" % b.getName() - outp(_justify_and_indent(_trim_doc_string(item), level, munge)) - level -= 1 - - namesAndDescriptions = I.namesAndDescriptions() - namesAndDescriptions.sort() - - outp(_justify_and_indent("Attributes:", level, munge)) - level += 1 - for name, desc in namesAndDescriptions: - if not hasattr(desc, 'getSignatureString'): # ugh... - item = "%s -- %s" % (desc.getName(), - desc.getDoc() or 'no documentation') - outp(_justify_and_indent(_trim_doc_string(item), level, munge)) - level -= 1 - - outp(_justify_and_indent("Methods:", level, munge)) - level += 1 - for name, desc in namesAndDescriptions: - if hasattr(desc, 'getSignatureString'): # ugh... - item = "%s%s -- %s" % (desc.getName(), - desc.getSignatureString(), - desc.getDoc() or 'no documentation') - outp(_justify_and_indent(_trim_doc_string(item), level, munge)) - - return "\n\n".join(r) + "\n\n" - - -def _trim_doc_string(text): - """ Trims a doc string to make it format - correctly with structured text. """ - - lines = text.replace('\r\n', '\n').split('\n') - nlines = [lines.pop(0)] - if lines: - min_indent = min([len(line) - len(line.lstrip()) - for line in lines]) - for line in lines: - nlines.append(line[min_indent:]) - - return '\n'.join(nlines) - - -def _justify_and_indent(text, level, munge=0, width=72): - """ indent and justify text, rejustify (munge) if specified """ - - indent = " " * level - - if munge: - lines = [] - line = indent - text = text.split() - - for word in text: - line = ' '.join([line, word]) - if len(line) > width: - lines.append(line) - line = indent - else: - lines.append(line) - - return '\n'.join(lines) - - else: - return indent + \ - text.strip().replace("\r\n", "\n") .replace("\n", "\n" + indent) diff --git a/src/zope/interface/exceptions.py b/src/zope/interface/exceptions.py deleted file mode 100644 index da0cf79..0000000 --- a/src/zope/interface/exceptions.py +++ /dev/null @@ -1,69 +0,0 @@ -############################################################################## -# -# Copyright (c) 2002 Zope Corporation 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. -# -############################################################################## -"""Interface-specific exceptions - -$Id$ -""" - -class Invalid(Exception): - """An specification is violated - """ - -class DoesNotImplement(Invalid): - """ This object does not implement """ - def __init__(self, interface): - self.interface = interface - - def __str__(self): - return """An object does not implement interface %(interface)s - - """ % self.__dict__ - -class BrokenImplementation(Invalid): - """An attribute is not completely implemented. - """ - - def __init__(self, interface, name): - self.interface=interface - self.name=name - - def __str__(self): - return """An object has failed to implement interface %(interface)s - - The %(name)s attribute was not provided. - """ % self.__dict__ - -class BrokenMethodImplementation(Invalid): - """An method is not completely implemented. - """ - - def __init__(self, method, mess): - self.method=method - self.mess=mess - - def __str__(self): - return """The implementation of %(method)s violates its contract - because %(mess)s. - """ % self.__dict__ - -class InvalidInterface(Exception): - """The interface has invalid contents - """ - -class BadImplements(TypeError): - """An implementation assertion is invalid - - because it doesn't contain an interface or a sequence of valid - implementation assertions. - """ diff --git a/src/zope/interface/human.txt b/src/zope/interface/human.txt deleted file mode 100644 index 5bb5574..0000000 --- a/src/zope/interface/human.txt +++ /dev/null @@ -1,152 +0,0 @@ -========================== -Using the Adapter Registry -========================== - -This is a small demonstration of the ``zope.interface`` package including its -adapter registry. It is intended to provide a concrete but narrow example on -how to use interfaces and adapters outside of Zope 3. - -First we have to import the interface package. - - >>> import zope.interface - -We now develop an interface for our object, which is a simple file in this -case. For now we simply support one attribute, the body, which contains the -actual file contents. - - >>> class IFile(zope.interface.Interface): - ... - ... body = zope.interface.Attribute('Contents of the file.') - ... - -For statistical reasons we often want to know the size of a file. However, it -would be clumsy to implement the size directly in the file object, since the -size really represents meta-data. Thus we create another interface that -provides the size of something. - - >>> class ISize(zope.interface.Interface): - ... - ... def getSize(): - ... 'Return the size of an object.' - ... - -Now we need to implement the file. It is essential that the object states -that it implements the `IFile` interface. We also provide a default body -value (just to make things simpler for this example). - - >>> class File(object): - ... - ... zope.interface.implements(IFile) - ... body = 'foo bar' - ... - -Next we implement an adapter that can provide the `ISize` interface given any -object providing `IFile`. By convention we use `__used_for__` to specify the -interface that we expect the adapted object to provide, in our case -`IFile`. However, this attribute is not used for anything. If you have -multiple interfaces for which an adapter is used, just specify the interfaces -via a tuple. - -Again by convention, the constructor of an adapter takes one argument, the -context. The context in this case is an instance of `File` (providing `IFile`) -that is used to extract the size from. Also by convention the context is -stored in an attribute named `context` on the adapter. The twisted community -refers to the context as the `original` object. However, you may feel free to -use a specific argument name, such as `file`. - - >>> class FileSize(object): - ... - ... zope.interface.implements(ISize) - ... __used_for__ = IFile - ... - ... def __init__(self, context): - ... self.context = context - ... - ... def getSize(self): - ... return len(self.context.body) - ... - -Now that we have written our adapter, we have to register it with an adapter -registry, so that it can be looked up when needed. There is no such thing as a -global registry; thus we have to instantiate one for our example manually. - - >>> from zope.interface.adapter import AdapterRegistry - >>> registry = AdapterRegistry() - - -The registry keeps a map of what adapters implement based on another -interface, the object already provides. Therefore, we next have to register an -adapter that adapts from `IFile` to `ISize`. The first argument to -the registry's `register()` method is a list of original interfaces.In our -cause we have only one original interface, `IFile`. A list makes sense, since -the interface package has the concept of multi-adapters, which are adapters -that require multiple objects to adapt to a new interface. In these -situations, your adapter constructor will require an argument for each -specified interface. - -The second argument is the interface the adapter provides, in our case -`ISize`. The third argument in the name of the adapter. Since we do not care -about names, we simply leave it as an empty string. Names are commonly useful, -if you have adapters for the same set of interfaces, but they are useful in -different situations. The last argument is simply the adapter class. - - >>> registry.register([IFile], ISize, '', FileSize) - -You can now use the the registry to lookup the adapter. - - >>> registry.lookup1(IFile, ISize, '') - <class '__main__.FileSize'> - -Let's get a little bit more practical. Let's create a `File` instance and -create the adapter using a registry lookup. Then we see whether the adapter -returns the correct size by calling `getSize()`. - - >>> file = File() - >>> size = registry.lookup1(IFile, ISize, '')(file) - >>> size.getSize() - 7 - -However, this is not very practical, since I have to manually pass in the -arguments to the lookup method. There is some syntactic candy that will allow -us to get an adapter instance by simply calling `ISize(file)`. To make use of -this functionality, we need to add our registry to the adapter_hooks list, -which is a member of the adapters module. This list stores a collection of -callables that are automatically invoked when IFoo(obj) is called; their -purpose is to locate adapters that implement an interface for a certain -context instance. - -You are required to implement your own adapter hook; this example covers one -of the simplest hooks that use the registry, but you could implement one that -used an adapter cache or persistent adapters, for instance. The helper hook is -required to expect as first argument the desired output interface (for us -`ISize`) and as the second argument the context of the adapter (here -`file`). The function returns an adapter, i.e. a `FileSize` instance. - - >>> def hook(provided, object): - ... adapter = registry.lookup1(zope.interface.providedBy(object), - ... provided, '') - ... return adapter(object) - ... - -We now just add the hook to an `adapter_hooks` list. - - >>> from zope.interface.interface import adapter_hooks - >>> adapter_hooks.append(hook) - -Once the hook is registered, you can use the desired syntax. - - >>> size = ISize(file) - >>> size.getSize() - 7 - -Now we have to cleanup after ourselves, so that others after us have a clean -`adapter_hooks` list. - - >>> adapter_hooks.remove(hook) - -That's it. I have intentionally left out a discussion of named adapters and -multi-adapters, since this text is intended as a practical and simple -introduction to Zope 3 interfaces and adapters. You might want to read the -`adapter.txt` in the `zope.interface` package for a more formal, referencial -and complete treatment of the package. Warning: People have reported that -`adapter.txt` makes their brain feel soft! diff --git a/src/zope/interface/interface.py b/src/zope/interface/interface.py deleted file mode 100644 index 5dd2233..0000000 --- a/src/zope/interface/interface.py +++ /dev/null @@ -1,916 +0,0 @@ -############################################################################## -# -# Copyright (c) 2001, 2002 Zope Corporation 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. -# -############################################################################## -"""Interface object implementation - -$Id$ -""" - -from __future__ import generators - -import sys -import warnings -import weakref -from types import FunctionType -from ro import ro -from zope.interface.exceptions import Invalid - -CO_VARARGS = 4 -CO_VARKEYWORDS = 8 -TAGGED_DATA = '__interface_tagged_values__' - -_decorator_non_return = object() - -def invariant(call): - f_locals = sys._getframe(1).f_locals - tags = f_locals.setdefault(TAGGED_DATA, {}) - invariants = tags.setdefault('invariants', []) - invariants.append(call) - return _decorator_non_return - -class Element(object): - - # We can't say this yet because we don't have enough - # infrastructure in place. - # - #implements(IElement) - - def __init__(self, __name__, __doc__=''): - """Create an 'attribute' description - """ - if not __doc__ and __name__.find(' ') >= 0: - __doc__ = __name__ - __name__ = None - - self.__name__=__name__ - self.__doc__=__doc__ - self.__tagged_values = {} - - def getName(self): - """ Returns the name of the object. """ - return self.__name__ - - def getDoc(self): - """ Returns the documentation for the object. """ - return self.__doc__ - - def getTaggedValue(self, tag): - """ Returns the value associated with 'tag'. """ - return self.__tagged_values[tag] - - def queryTaggedValue(self, tag, default=None): - """ Returns the value associated with 'tag'. """ - return self.__tagged_values.get(tag, default) - - def getTaggedValueTags(self): - """ Returns a list of all tags. """ - return self.__tagged_values.keys() - - def setTaggedValue(self, tag, value): - """ Associates 'value' with 'key'. """ - self.__tagged_values[tag] = value - -class SpecificationBasePy(object): - - def providedBy(self, ob): - """Is the interface implemented by an object - - >>> from zope.interface import * - >>> class I1(Interface): - ... pass - >>> class C(object): - ... implements(I1) - >>> c = C() - >>> class X(object): - ... pass - >>> x = X() - >>> I1.providedBy(x) - False - >>> I1.providedBy(C) - False - >>> I1.providedBy(c) - True - >>> directlyProvides(x, I1) - >>> I1.providedBy(x) - True - >>> directlyProvides(C, I1) - >>> I1.providedBy(C) - True - - """ - spec = providedBy(ob) - return self in spec._implied - - def implementedBy(self, cls): - """Test whether the specification is implemented by a class or factory. - Raise TypeError if argument is neither a class nor a callable.""" - spec = implementedBy(cls) - return self in spec._implied - - def isOrExtends(self, interface): - """Is the interface the same as or extend the given interface - - Examples:: - - >>> from zope.interface import Interface - >>> from zope.interface.declarations import Declaration - >>> class I1(Interface): pass - ... - >>> class I2(I1): pass - ... - >>> class I3(Interface): pass - ... - >>> class I4(I3): pass - ... - >>> spec = Declaration() - >>> int(spec.extends(Interface)) - 0 - >>> spec = Declaration(I2) - >>> int(spec.extends(Interface)) - 1 - >>> int(spec.extends(I1)) - 1 - >>> int(spec.extends(I2)) - 1 - >>> int(spec.extends(I3)) - 0 - >>> int(spec.extends(I4)) - 0 - - """ - return interface in self._implied - -SpecificationBase = SpecificationBasePy - -try: - from _zope_interface_coptimizations import SpecificationBase -except ImportError: - pass - -class Specification(SpecificationBase): - """Specifications - - An interface specification is used to track interface declarations - and component registrations. - - This class is a base class for both interfaces themselves and for - interface specifications (declarations). - - Specifications are mutable. If you reassign their cases, their - relations with other specifications are adjusted accordingly. - - For example: - - >>> from zope.interface import Interface - >>> class I1(Interface): - ... pass - >>> class I2(I1): - ... pass - >>> class I3(I2): - ... pass - - >>> [i.__name__ for i in I1.__bases__] - ['Interface'] - - >>> [i.__name__ for i in I2.__bases__] - ['I1'] - - >>> I3.extends(I1) - 1 - - >>> I2.__bases__ = (Interface, ) - - >>> [i.__name__ for i in I2.__bases__] - ['Interface'] - - >>> I3.extends(I1) - 0 - - """ - - # Copy some base class methods for speed - isOrExtends = SpecificationBase.isOrExtends - providedBy = SpecificationBase.providedBy - - ######################################################################### - # BBB 2004-07-13: Backward compatabilty. These methods have been - # deprecated in favour of providedBy and implementedBy. - - def isImplementedByInstancesOf(self, cls): - warnings.warn( - "isImplementedByInstancesOf has been renamed to implementedBy", - DeprecationWarning, stacklevel=2, - ) - return self.implementedBy(cls) - - def isImplementedBy(self, ob): - warnings.warn( - "isImplementedBy has been renamed to providedBy", - DeprecationWarning, stacklevel=2, - ) - return self.providedBy(ob) - # - ######################################################################### - - def __init__(self, bases=()): - self._implied = {} - self.dependents = weakref.WeakKeyDictionary() - self.__bases__ = tuple(bases) - - def subscribe(self, dependent): - self.dependents[dependent] = self.dependents.get(dependent, 0) + 1 - - def unsubscribe(self, dependent): - n = self.dependents.get(dependent, 0) - 1 - if not n: - del self.dependents[dependent] - elif n > 0: - self.dependents[dependent] = n - else: - raise KeyError(dependent) - - def __setBases(self, bases): - # Register ourselves as a dependent of our old bases - for b in self.__bases__: - b.unsubscribe(self) - - # Register ourselves as a dependent of our bases - self.__dict__['__bases__'] = bases - for b in bases: - b.subscribe(self) - - self.changed() - - __bases__ = property( - - lambda self: self.__dict__.get('__bases__', ()), - __setBases, - ) - - def changed(self): - """We, or something we depend on, have changed - """ - - implied = self._implied - implied.clear() - - ancestors = ro(self) - self.__sro__ = tuple(ancestors) - self.__iro__ = tuple([ancestor for ancestor in ancestors - if isinstance(ancestor, InterfaceClass) - ]) - - for ancestor in ancestors: - # We directly imply our ancestors: - implied[ancestor] = () - - # Now, advise our dependents of change: - for dependent in self.dependents.keys(): - dependent.changed() - - - def interfaces(self): - """Return an iterator for the interfaces in the specification - - for example:: - - >>> from zope.interface import Interface - >>> class I1(Interface): pass - ... - >>> class I2(I1): pass - ... - >>> class I3(Interface): pass - ... - >>> class I4(I3): pass - ... - >>> spec = Specification((I2, I3)) - >>> spec = Specification((I4, spec)) - >>> i = spec.interfaces() - >>> i.next().getName() - 'I4' - >>> i.next().getName() - 'I2' - >>> i.next().getName() - 'I3' - >>> list(i) - [] - """ - seen = {} - for base in self.__bases__: - for interface in base.interfaces(): - if interface not in seen: - seen[interface] = 1 - yield interface - - - def extends(self, interface, strict=True): - """Does the specification extend the given interface? - - Test whether an interface in the specification extends the - given interface - - Examples:: - - >>> from zope.interface import Interface - >>> from zope.interface.declarations import Declaration - >>> class I1(Interface): pass - ... - >>> class I2(I1): pass - ... - >>> class I3(Interface): pass - ... - >>> class I4(I3): pass - ... - >>> spec = Declaration() - >>> int(spec.extends(Interface)) - 0 - >>> spec = Declaration(I2) - >>> int(spec.extends(Interface)) - 1 - >>> int(spec.extends(I1)) - 1 - >>> int(spec.extends(I2)) - 1 - >>> int(spec.extends(I3)) - 0 - >>> int(spec.extends(I4)) - 0 - >>> I2.extends(I2) - 0 - >>> I2.extends(I2, False) - 1 - >>> I2.extends(I2, strict=False) - 1 - - """ - return ((interface in self._implied) - and - ((not strict) or (self != interface)) - ) - - def weakref(self, callback=None): - return weakref.ref(self, callback) - - def get(self, name, default=None): - """Query for an attribute description - """ - try: - attrs = self._v_attrs - except AttributeError: - attrs = self._v_attrs = {} - attr = attrs.get(name) - if attr is None: - for iface in self.__iro__: - attr = iface.direct(name) - if attr is not None: - attrs[name] = attr - break - - if attr is None: - return default - else: - return attr - -class InterfaceClass(Element, Specification): - """Prototype (scarecrow) Interfaces Implementation.""" - - # We can't say this yet because we don't have enough - # infrastructure in place. - # - #implements(IInterface) - - def __init__(self, name, bases=(), attrs=None, __doc__=None, - __module__=None): - - if attrs is None: - attrs = {} - - if __module__ is None: - __module__ = attrs.get('__module__') - if isinstance(__module__, str): - del attrs['__module__'] - else: - try: - # Figure out what module defined the interface. - # This is how cPython figures out the module of - # a class, but of course it does it in C. :-/ - __module__ = sys._getframe(1).f_globals['__name__'] - except (AttributeError, KeyError): - pass - - self.__module__ = __module__ - - d = attrs.get('__doc__') - if d is not None: - if not isinstance(d, Attribute): - if __doc__ is None: - __doc__ = d - del attrs['__doc__'] - - if __doc__ is None: - __doc__ = '' - - Element.__init__(self, name, __doc__) - - tagged_data = attrs.pop(TAGGED_DATA, None) - if tagged_data is not None: - for key, val in tagged_data.items(): - self.setTaggedValue(key, val) - - for base in bases: - if not isinstance(base, InterfaceClass): - raise TypeError('Expected base interfaces') - - Specification.__init__(self, bases) - - # Make sure that all recorded attributes (and methods) are of type - # `Attribute` and `Method` - for name, attr in attrs.items(): - if isinstance(attr, Attribute): - attr.interface = self - if not attr.__name__: - attr.__name__ = name - elif isinstance(attr, FunctionType): - attrs[name] = fromFunction(attr, self, name=name) - elif attr is _decorator_non_return: - del attrs[name] - else: - raise InvalidInterface("Concrete attribute, " + name) - - self.__attrs = attrs - - self.__identifier__ = "%s.%s" % (self.__module__, self.__name__) - - def interfaces(self): - """Return an iterator for the interfaces in the specification - - for example:: - - >>> from zope.interface import Interface - >>> class I1(Interface): pass - ... - >>> - >>> i = I1.interfaces() - >>> i.next().getName() - 'I1' - >>> list(i) - [] - """ - yield self - - def getBases(self): - return self.__bases__ - - def isEqualOrExtendedBy(self, other): - """Same interface or extends?""" - return self == other or other.extends(self) - - def names(self, all=False): - """Return the attribute names defined by the interface.""" - if not all: - return self.__attrs.keys() - - r = self.__attrs.copy() - - for base in self.__bases__: - r.update(dict.fromkeys(base.names(all))) - - return r.keys() - - def __iter__(self): - return iter(self.names(all=True)) - - def namesAndDescriptions(self, all=False): - """Return attribute names and descriptions defined by interface.""" - if not all: - return self.__attrs.items() - - r = {} - for base in self.__bases__[::-1]: - r.update(dict(base.namesAndDescriptions(all))) - - r.update(self.__attrs) - - return r.items() - - def getDescriptionFor(self, name): - """Return the attribute description for the given name.""" - r = self.get(name) - if r is not None: - return r - - raise KeyError(name) - - __getitem__ = getDescriptionFor - - def __contains__(self, name): - return self.get(name) is not None - - def direct(self, name): - return self.__attrs.get(name) - - def queryDescriptionFor(self, name, default=None): - return self.get(name, default) - - def deferred(self): - """Return a defered class corresponding to the interface.""" - if hasattr(self, "_deferred"): return self._deferred - - klass={} - exec "class %s: pass" % self.__name__ in klass - klass=klass[self.__name__] - - self.__d(klass.__dict__) - - self._deferred=klass - - return klass - - def validateInvariants(self, obj, errors=None): - """validate object to defined invariants.""" - for call in self.queryTaggedValue('invariants', []): - try: - call(obj) - except Invalid, e: - if errors is None: - raise - else: - errors.append(e) - for base in self.__bases__: - try: - base.validateInvariants(obj, errors) - except Invalid: - if errors is None: - raise - if errors: - raise Invalid(errors) - - def _getInterface(self, ob, name): - """Retrieve a named interface.""" - return None - - def __d(self, dict): - - for k, v in self.__attrs.items(): - if isinstance(v, Method) and not (k in dict): - dict[k]=v - - for b in self.__bases__: - b.__d(dict) - - def __repr__(self): - try: - return self._v_repr - except AttributeError: - name = self.__name__ - m = self.__module__ - if m: - name = '%s.%s' % (m, name) - r = "<%s %s>" % (self.__class__.__name__, name) - self._v_repr = r - return r - - def __call__(): - # Mind the closure. It serves to keep a unique marker around to - # allow for an optional argument to __call__ without resorting - # to a global marker. - # - # This provides some consistency with the PEP 246 adapt method. - - marker = object() - - def __call__(self, obj, alternate=marker): - """Adapt an object to the interface - - The sematics based on those of the PEP 246 adapt function. - - If an object cannot be adapted, then a TypeError is raised:: - - >>> import zope.interface - >>> class I(zope.interface.Interface): - ... pass - - >>> I(0) - Traceback (most recent call last): - ... - TypeError: ('Could not adapt', 0, """ \ - """<InterfaceClass zope.interface.interface.I>) - - unless an alternate value is provided as a second - positional argument:: - - >>> I(0, 'bob') - 'bob' - - If an object already implements the interface, then it will be - returned:: - - >>> class C(object): - ... zope.interface.implements(I) - - >>> obj = C() - >>> I(obj) is obj - True - - If an object implements __conform__, then it will be used:: - - >>> class C(object): - ... zope.interface.implements(I) - ... def __conform__(self, proto): - ... return 0 - - >>> I(C()) - 0 - - Adapter hooks (see __adapt__) will also be used, if present: - - >>> from zope.interface.interface import adapter_hooks - >>> def adapt_0_to_42(iface, obj): - ... if obj == 0: - ... return 42 - - >>> adapter_hooks.append(adapt_0_to_42) - >>> I(0) - 42 - - >>> adapter_hooks.remove(adapt_0_to_42) - >>> I(0) - Traceback (most recent call last): - ... - TypeError: ('Could not adapt', 0, """ \ - """<InterfaceClass zope.interface.interface.I>) - - """ - conform = getattr(obj, '__conform__', None) - if conform is not None: - try: - adapter = conform(self) - except TypeError: - # We got a TypeError. It might be an error raised by - # the __conform__ implementation, or *we* may have - # made the TypeError by calling an unbound method - # (object is a class). In the later case, we behave - # as though there is no __conform__ method. We can - # detect this case by checking whether there is more - # than one traceback object in the traceback chain: - if sys.exc_info()[2].tb_next is not None: - # There is more than one entry in the chain, so - # reraise the error: - raise - # This clever trick is from Phillip Eby - else: - if adapter is not None: - return adapter - - adapter = self.__adapt__(obj) - - if adapter is not None: - return adapter - elif alternate is not marker: - return alternate - else: - raise TypeError("Could not adapt", obj, self) - - return __call__ - - __call__ = __call__() # Make the closure the *real* __call__ method. - - def __adapt__(self, obj): - """Adapt an object to the reciever - - This method is normally not called directly. It is called by - the PEP 246 adapt framework and by the interface __call__ - operator. - - The adapt method is responsible for adapting an object to - the reciever. - - The default version returns None:: - - >>> import zope.interface - >>> class I(zope.interface.Interface): - ... pass - - >>> I.__adapt__(0) - - unless the object given provides the interface:: - - >>> class C(object): - ... zope.interface.implements(I) - - >>> obj = C() - >>> I.__adapt__(obj) is obj - True - - Adapter hooks can be provided (or removed) to provide custom - adaptation. We'll install a silly hook that adapts 0 to 42. - We install a hook by simply adding it to the adapter_hooks - list:: - - >>> from zope.interface.interface import adapter_hooks - >>> def adapt_0_to_42(iface, obj): - ... if obj == 0: - ... return 42 - - >>> adapter_hooks.append(adapt_0_to_42) - >>> I.__adapt__(0) - 42 - - Hooks must either return an adapter, or None if no adapter can - be found. - - Hooks can be uninstalled by removing them from the list:: - - >>> adapter_hooks.remove(adapt_0_to_42) - >>> I.__adapt__(0) - - """ - if self.providedBy(obj): - return obj - - for hook in adapter_hooks: - adapter = hook(self, obj) - if adapter is not None: - return adapter - - def __reduce__(self): - return self.__name__ - - def __cmp(self, o1, o2): - # Yes, I did mean to name this __cmp, rather than __cmp__. - # It is a private method used by __lt__ and __gt__. - # I don't want to override __eq__ because I want the default - # __eq__, which is really fast. - """Make interfaces sortable - - TODO: It would ne nice if: - - More specific interfaces should sort before less specific ones. - Otherwise, sort on name and module. - - But this is too complicated, and we're going to punt on it - for now. - - For now, sort on interface and module name. - - None is treated as a pseudo interface that implies the loosest - contact possible, no contract. For that reason, all interfaces - sort before None. - - """ - if o1 == o2: - return 0 - - if o1 is None: - return 1 - if o2 is None: - return -1 - - n1 = (getattr(o1, '__name__', ''), - getattr(getattr(o1, '__module__', None), '__name__', '')) - n2 = (getattr(o2, '__name__', ''), - getattr(getattr(o2, '__module__', None), '__name__', '')) - - return cmp(n1, n2) - - def __lt__(self, other): - c = self.__cmp(self, other) - #print '<', self, other, c < 0, c - return c < 0 - - def __gt__(self, other): - c = self.__cmp(self, other) - #print '>', self, other, c > 0, c - return c > 0 - - -adapter_hooks = [] - -Interface = InterfaceClass("Interface", __module__ = 'zope.interface') - -class Attribute(Element): - """Attribute descriptions - """ - - # We can't say this yet because we don't have enough - # infrastructure in place. - # - # implements(IAttribute) - - interface = None - - -class Method(Attribute): - """Method interfaces - - The idea here is that you have objects that describe methods. - This provides an opportunity for rich meta-data. - """ - - # We can't say this yet because we don't have enough - # infrastructure in place. - # - # implements(IMethod) - - def __call__(self, *args, **kw): - raise BrokenImplementation(self.interface, self.__name__) - - def getSignatureInfo(self): - return {'positional': self.positional, - 'required': self.required, - 'optional': self.optional, - 'varargs': self.varargs, - 'kwargs': self.kwargs, - } - - def getSignatureString(self): - sig = [] - for v in self.positional: - sig.append(v) - if v in self.optional.keys(): - sig[-1] += "=" + `self.optional[v]` - if self.varargs: - sig.append("*" + self.varargs) - if self.kwargs: - sig.append("**" + self.kwargs) - - return "(%s)" % ", ".join(sig) - - -def fromFunction(func, interface=None, imlevel=0, name=None): - name = name or func.__name__ - method = Method(name, func.__doc__) - defaults = func.func_defaults or () - code = func.func_code - # Number of positional arguments - na = code.co_argcount-imlevel - names = code.co_varnames[imlevel:] - opt = {} - # Number of required arguments - nr = na-len(defaults) - if nr < 0: - defaults=defaults[-nr:] - nr = 0 - - # Determine the optional arguments. - opt.update(dict(zip(names[nr:], defaults))) - - method.positional = names[:na] - method.required = names[:nr] - method.optional = opt - - argno = na - - # Determine the function's variable argument's name (i.e. *args) - if code.co_flags & CO_VARARGS: - method.varargs = names[argno] - argno = argno + 1 - else: - method.varargs = None - - # Determine the function's keyword argument's name (i.e. **kw) - if code.co_flags & CO_VARKEYWORDS: - method.kwargs = names[argno] - else: - method.kwargs = None - - method.interface = interface - - for key, value in func.__dict__.items(): - method.setTaggedValue(key, value) - - return method - - -def fromMethod(meth, interface=None, name=None): - func = meth.im_func - return fromFunction(func, interface, imlevel=1, name=name) - - -# Now we can create the interesting interfaces and wire them up: -def _wire(): - from zope.interface.declarations import classImplements - - from zope.interface.interfaces import IAttribute - classImplements(Attribute, IAttribute) - - from zope.interface.interfaces import IMethod - classImplements(Method, IMethod) - - from zope.interface.interfaces import IInterface - classImplements(InterfaceClass, IInterface) - -# We import this here to deal with module dependencies. -from zope.interface.declarations import providedBy, implementedBy -from zope.interface.exceptions import InvalidInterface -from zope.interface.exceptions import BrokenImplementation diff --git a/src/zope/interface/interfaces.py b/src/zope/interface/interfaces.py deleted file mode 100644 index 4e00188..0000000 --- a/src/zope/interface/interfaces.py +++ /dev/null @@ -1,670 +0,0 @@ -############################################################################## -# -# Copyright (c) 2002 Zope Corporation 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. -# -############################################################################## -"""Interface Package Interfaces - -$Id$ -""" -__docformat__ = 'restructuredtext' - - -from zope.interface import Interface -from zope.interface.interface import Attribute - -class IElement(Interface): - """Objects that have basic documentation and tagged values. - """ - - __name__ = Attribute('__name__', 'The object name') - __doc__ = Attribute('__doc__', 'The object doc string') - - def getTaggedValue(tag): - """Returns the value associated with `tag`. - - Raise a `KeyError` of the tag isn't set. - """ - - def queryTaggedValue(tag, default=None): - """Returns the value associated with `tag`. - - Return the default value of the tag isn't set. - """ - - def getTaggedValueTags(): - """Returns a list of all tags.""" - - def setTaggedValue(tag, value): - """Associates `value` with `key`.""" - - -class IAttribute(IElement): - """Attribute descriptors""" - - interface = Attribute('interface', - 'Stores the interface instance in which the ' - 'attribute is located.') - - -class IMethod(IAttribute): - """Method attributes""" - - def getSignatureInfo(): - """Returns the signature information. - - This method returns a dictionary with the following keys: - - o `positional` - All positional arguments. - - o `required` - A list of all required arguments. - - o `optional` - A list of all optional arguments. - - o `varargs` - The name of the varargs argument. - - o `kwargs` - The name of the kwargs argument. - """ - - def getSignatureString(): - """Return a signature string suitable for inclusion in documentation. - - This method returns the function signature string. For example, if you - have `func(a, b, c=1, d='f')`, then the signature string is `(a, b, - c=1, d='f')`. - """ - -class ISpecification(Interface): - """Object Behavioral specifications""" - - def extends(other, strict=True): - """Test whether a specification extends another - - The specification extends other if it has other as a base - interface or if one of it's bases extends other. - - If strict is false, then the specification extends itself. - """ - - def isOrExtends(other): - """Test whether the specification is or extends another - """ - - def weakref(callback=None): - """Return a weakref to the specification - - This method is, regrettably, needed to allow weakrefs to be - computed to security-proxied specifications. While the - zope.interface package does not require zope.security or - zope.proxy, it has to be able to coexist with it. - - """ - - __bases__ = Attribute("""Base specifications - - A tuple if specifications from which this specification is - directly derived. - - """) - - __sro__ = Attribute("""Specification-resolution order - - A tuple of the specification and all of it's ancestor - specifications from most specific to least specific. - - (This is similar to the method-resolution order for new-style classes.) - """) - - def get(name, default=None): - """Look up the description for a name - - If the named attribute is not defined, the default is - returned. - """ - - -class IInterface(ISpecification, IElement): - """Interface objects - - Interface objects describe the behavior of an object by containing - useful information about the object. This information includes: - - o Prose documentation about the object. In Python terms, this - is called the "doc string" of the interface. In this element, - you describe how the object works in prose language and any - other useful information about the object. - - o Descriptions of attributes. Attribute descriptions include - the name of the attribute and prose documentation describing - the attributes usage. - - o Descriptions of methods. Method descriptions can include: - - - Prose "doc string" documentation about the method and its - usage. - - - A description of the methods arguments; how many arguments - are expected, optional arguments and their default values, - the position or arguments in the signature, whether the - method accepts arbitrary arguments and whether the method - accepts arbitrary keyword arguments. - - o Optional tagged data. Interface objects (and their attributes and - methods) can have optional, application specific tagged data - associated with them. Examples uses for this are examples, - security assertions, pre/post conditions, and other possible - information you may want to associate with an Interface or its - attributes. - - Not all of this information is mandatory. For example, you may - only want the methods of your interface to have prose - documentation and not describe the arguments of the method in - exact detail. Interface objects are flexible and let you give or - take any of these components. - - Interfaces are created with the Python class statement using - either Interface.Interface or another interface, as in:: - - from zope.interface import Interface - - class IMyInterface(Interface): - '''Interface documentation''' - - def meth(arg1, arg2): - '''Documentation for meth''' - - # Note that there is no self argument - - class IMySubInterface(IMyInterface): - '''Interface documentation''' - - def meth2(): - '''Documentation for meth2''' - - You use interfaces in two ways: - - o You assert that your object implement the interfaces. - - There are several ways that you can assert that an object - implements an interface: - - 1. Call zope.interface.implements in your class definition. - - 2. Call zope.interfaces.directlyProvides on your object. - - 3. Call 'zope.interface.classImplements' to assert that instances - of a class implement an interface. - - For example:: - - from zope.interface import classImplements - - classImplements(some_class, some_interface) - - This approach is useful when it is not an option to modify - the class source. Note that this doesn't affect what the - class itself implements, but only what its instances - implement. - - o You query interface meta-data. See the IInterface methods and - attributes for details. - - """ - - def providedBy(object): - """Test whether the interface is implemented by the object - - Return true of the object asserts that it implements the - interface, including asserting that it implements an extended - interface. - """ - - def implementedBy(class_): - """Test whether the interface is implemented by instances of the class - - Return true of the class asserts that its instances implement the - interface, including asserting that they implement an extended - interface. - """ - - def names(all=False): - """Get the interface attribute names - - Return a sequence of the names of the attributes, including - methods, included in the interface definition. - - Normally, only directly defined attributes are included. If - a true positional or keyword argument is given, then - attributes defined by base classes will be included. - """ - - def namesAndDescriptions(all=False): - """Get the interface attribute names and descriptions - - Return a sequence of the names and descriptions of the - attributes, including methods, as name-value pairs, included - in the interface definition. - - Normally, only directly defined attributes are included. If - a true positional or keyword argument is given, then - attributes defined by base classes will be included. - """ - - def __getitem__(name): - """Get the description for a name - - If the named attribute is not defined, a KeyError is raised. - """ - - def direct(name): - """Get the description for the name if it was defined by the interface - - If the interface doesn't define the name, returns None. - """ - - def validateInvariants(obj, errors=None): - """Validate invariants - - Validate object to defined invariants. If errors is None, - raises first Invalid error; if errors is a list, appends all errors - to list, then raises Invalid with the errors as the first element - of the "args" tuple.""" - - def __contains__(name): - """Test whether the name is defined by the interface""" - - def __iter__(): - """Return an iterator over the names defined by the interface - - The names iterated include all of the names defined by the - interface directly and indirectly by base interfaces. - """ - - __module__ = Attribute("""The name of the module defining the interface""") - -class IDeclaration(ISpecification): - """Interface declaration - - Declarations are used to express the interfaces implemented by - classes or provided by objects. - """ - - def __contains__(interface): - """Test whether an interface is in the specification - - Return true if the given interface is one of the interfaces in - the specification and false otherwise. - """ - - def __iter__(): - """Return an iterator for the interfaces in the specification - """ - - def flattened(): - """Return an iterator of all included and extended interfaces - - An iterator is returned for all interfaces either included in - or extended by interfaces included in the specifications - without duplicates. The interfaces are in "interface - resolution order". The interface resolution order is such that - base interfaces are listed after interfaces that extend them - and, otherwise, interfaces are included in the order that they - were defined in the specification. - """ - - def __sub__(interfaces): - """Create an interface specification with some interfaces excluded - - The argument can be an interface or an interface - specifications. The interface or interfaces given in a - specification are subtracted from the interface specification. - - Removing an interface that is not in the specification does - not raise an error. Doing so has no effect. - - Removing an interface also removes sub-interfaces of the interface. - - """ - - def __add__(interfaces): - """Create an interface specification with some interfaces added - - The argument can be an interface or an interface - specifications. The interface or interfaces given in a - specification are added to the interface specification. - - Adding an interface that is already in the specification does - not raise an error. Doing so has no effect. - """ - - def __nonzero__(): - """Return a true value of the interface specification is non-empty - """ - -class IInterfaceDeclaration(Interface): - """Declare and check the interfaces of objects - - The functions defined in this interface are used to declare the - interfaces that objects provide and to query the interfaces that have - been declared. - - Interfaces can be declared for objects in two ways: - - - Interfaces are declared for instances of the object's class - - - Interfaces are declared for the object directly. - - The interfaces declared for an object are, therefore, the union of - interfaces declared for the object directly and the interfaces - declared for instances of the object's class. - - Note that we say that a class implements the interfaces provided - by it's instances. An instance can also provide interfaces - directly. The interfaces provided by an object are the union of - the interfaces provided directly and the interfaces implemented by - the class. - """ - - def providedBy(ob): - """Return the interfaces provided by an object - - This is the union of the interfaces directly provided by an - object and interfaces implemented by it's class. - - The value returned is an IDeclaration. - """ - - def implementedBy(class_): - """Return the interfaces implemented for a class' instances - - The value returned is an IDeclaration. - """ - - def classImplements(class_, *interfaces): - """Declare additional interfaces implemented for instances of a class - - The arguments after the class are one or more interfaces or - interface specifications (IDeclaration objects). - - The interfaces given (including the interfaces in the - specifications) are added to any interfaces previously - declared. - - Consider the following example:: - - class C(A, B): - ... - - classImplements(C, I1, I2) - - - Instances of ``C`` provide ``I1``, ``I2``, and whatever interfaces - instances of ``A`` and ``B`` provide. - """ - - def implementer(*interfaces): - """Create a decorator for declaring interfaces implemented by a facory - - A callable is returned that makes an implements declaration on - objects passed to it. - """ - - def classImplementsOnly(class_, *interfaces): - """Declare the only interfaces implemented by instances of a class - - The arguments after the class are one or more interfaces or - interface specifications (IDeclaration objects). - - The interfaces given (including the interfaces in the - specifications) replace any previous declarations. - - Consider the following example:: - - class C(A, B): - ... - - classImplements(C, IA, IB. IC) - classImplementsOnly(C. I1, I2) - - Instances of ``C`` provide only ``I1``, ``I2``, and regardless of - whatever interfaces instances of ``A`` and ``B`` implement. - """ - - def directlyProvidedBy(object): - """Return the interfaces directly provided by the given object - - The value returned is an IDeclaration. - """ - - def directlyProvides(object, *interfaces): - """Declare interfaces declared directly for an object - - The arguments after the object are one or more interfaces or - interface specifications (IDeclaration objects). - - The interfaces given (including the interfaces in the - specifications) replace interfaces previously - declared for the object. - - Consider the following example:: - - class C(A, B): - ... - - ob = C() - directlyProvides(ob, I1, I2) - - The object, ``ob`` provides ``I1``, ``I2``, and whatever interfaces - instances have been declared for instances of ``C``. - - To remove directly provided interfaces, use ``directlyProvidedBy`` and - subtract the unwanted interfaces. For example:: - - directlyProvides(ob, directlyProvidedBy(ob)-I2) - - removes I2 from the interfaces directly provided by - ``ob``. The object, ``ob`` no longer directly provides ``I2``, - although it might still provide ``I2`` if it's class - implements ``I2``. - - To add directly provided interfaces, use ``directlyProvidedBy`` and - include additional interfaces. For example:: - - directlyProvides(ob, directlyProvidedBy(ob), I2) - - adds I2 to the interfaces directly provided by ob. - """ - - def implements(*interfaces): - """Declare interfaces implemented by instances of a class - - This function is called in a class definition. - - The arguments are one or more interfaces or interface - specifications (IDeclaration objects). - - The interfaces given (including the interfaces in the - specifications) are added to any interfaces previously - declared. - - Previous declarations include declarations for base classes - unless implementsOnly was used. - - This function is provided for convenience. It provides a more - convenient way to call classImplements. For example:: - - implements(I1) - - is equivalent to calling:: - - classImplements(C, I1) - - after the class has been created. - - Consider the following example:: - - class C(A, B): - implements(I1, I2) - - - Instances of ``C`` implement ``I1``, ``I2``, and whatever interfaces - instances of ``A`` and ``B`` implement. - """ - - def implementsOnly(*interfaces): - """Declare the only interfaces implemented by instances of a class - - This function is called in a class definition. - - The arguments are one or more interfaces or interface - specifications (IDeclaration objects). - - Previous declarations including declarations for base classes - are overridden. - - This function is provided for convenience. It provides a more - convenient way to call classImplementsOnly. For example:: - - implementsOnly(I1) - - is equivalent to calling:: - - classImplementsOnly(I1) - - after the class has been created. - - Consider the following example:: - - class C(A, B): - implementsOnly(I1, I2) - - - Instances of ``C`` implement ``I1``, ``I2``, regardless of what - instances of ``A`` and ``B`` implement. - """ - - def classProvides(*interfaces): - """Declare interfaces provided directly by a class - - This function is called in a class definition. - - The arguments are one or more interfaces or interface - specifications (IDeclaration objects). - - The given interfaces (including the interfaces in the - specifications) are used to create the class's direct-object - interface specification. An error will be raised if the module - class has an direct interface specification. In other words, it is - an error to call this function more than once in a class - definition. - - Note that the given interfaces have nothing to do with the - interfaces implemented by instances of the class. - - This function is provided for convenience. It provides a more - convenient way to call directlyProvides for a class. For example:: - - classProvides(I1) - - is equivalent to calling:: - - directlyProvides(theclass, I1) - - after the class has been created. - """ - - def moduleProvides(*interfaces): - """Declare interfaces provided by a module - - This function is used in a module definition. - - The arguments are one or more interfaces or interface - specifications (IDeclaration objects). - - The given interfaces (including the interfaces in the - specifications) are used to create the module's direct-object - interface specification. An error will be raised if the module - already has an interface specification. In other words, it is - an error to call this function more than once in a module - definition. - - This function is provided for convenience. It provides a more - convenient way to call directlyProvides for a module. For example:: - - moduleImplements(I1) - - is equivalent to:: - - directlyProvides(sys.modules[__name__], I1) - """ - - def Declaration(*interfaces): - """Create an interface specification - - The arguments are one or more interfaces or interface - specifications (IDeclaration objects). - - A new interface specification (IDeclaration) with - the given interfaces is returned. - """ - -class IAdapterRegistry(Interface): - """Provide an interface-based registry for adapters - - This registry registers objects that are in some sense "from" a - sequence of specification to an interface and a name. - - No specific semantics are assumed for the registered objects, - however, the most common application will be to register factories - that adapt objects providing required specifications to a provided - interface. - """ - - def register(required, provided, name, value): - """Register a value - - A value is registered for a *sequence* of required specifications, a - provided interface, and a name. - """ - - def lookup(required, provided, name, default=None): - """Lookup a value - - A value is looked up based on a *sequence* of required - specifications, a provided interface, and a name. - """ - - def lookupAll(required, provided): - """Find all adapters from the required to the provided interfaces - - An iterable object is returned that provides name-value two-tuples. - """ - - def names(required, provided): - """Return the names for which there are registered objects - """ - - def subscribe(required, provided, subscriber): - """Register a subscriber - - A subscriber is registered for a *sequence* of required - specifications, a provided interface, and a name. - - Multiple subscribers may be registered for the same (or - equivalent) interfaces. - """ - - def subscriptions(required, provided): - """Get a sequence of subscribers - - Subscribers for a *sequence* of required interfaces, and a provided - interface are returned. - """ diff --git a/src/zope/interface/ro.py b/src/zope/interface/ro.py deleted file mode 100644 index 01526bf..0000000 --- a/src/zope/interface/ro.py +++ /dev/null @@ -1,63 +0,0 @@ -############################################################################## -# -# Copyright (c) 2003 Zope Corporation 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. -# -############################################################################## -"""Compute a resolution order for an object and it's bases - -$Id$ -""" - -def ro(object): - """Compute a "resolution order" for an object - """ - return mergeOrderings([_flatten(object, [])]) - -def mergeOrderings(orderings, seen=None): - """Merge multiple orderings so that within-ordering order is preserved - - Orderings are constrained in such a way that if an object appears - in two or more orderings, then the suffix that begins with the - object must be in both orderings. - - For example: - - >>> _mergeOrderings([ - ... ['x', 'y', 'z'], - ... ['q', 'z'], - ... [1, 3, 5], - ... ['z'] - ... ]) - ['x', 'y', 'q', 1, 3, 5, 'z'] - - """ - - if seen is None: - seen = {} - result = [] - orderings.reverse() - for ordering in orderings: - ordering = list(ordering) - ordering.reverse() - for o in ordering: - if o not in seen: - seen[o] = 1 - result.append(o) - - result.reverse() - return result - -def _flatten(ob, result): - result.append(ob) - for base in ob.__bases__: - _flatten(base, result) - - return result diff --git a/src/zope/interface/tests/__init__.py b/src/zope/interface/tests/__init__.py deleted file mode 100644 index b711d36..0000000 --- a/src/zope/interface/tests/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# -# This file is necessary to make this directory a package. diff --git a/src/zope/interface/tests/dummy.py b/src/zope/interface/tests/dummy.py deleted file mode 100644 index f4a4f9d..0000000 --- a/src/zope/interface/tests/dummy.py +++ /dev/null @@ -1,25 +0,0 @@ -############################################################################## -# -# Copyright (c) 2001, 2002 Zope Corporation 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. -# -############################################################################## -"""Dummy Module - -$Id$ -""" -from zope.interface import moduleProvides -from zope.interface.tests.ifoo import IFoo -from zope.interface import moduleProvides - -moduleProvides(IFoo) - -def bar(baz): - pass diff --git a/src/zope/interface/tests/foodforthought.txt b/src/zope/interface/tests/foodforthought.txt deleted file mode 100644 index 45d961b..0000000 --- a/src/zope/interface/tests/foodforthought.txt +++ /dev/null @@ -1,61 +0,0 @@ -================================ -Food-based subscription examples -================================ - - -This file gives more subscription examples using a cooking-based example:: - - >>> from zope.interface.adapter import AdapterRegistry - >>> registry = AdapterRegistry() - - >>> import zope.interface - >>> class IAnimal(zope.interface.Interface): - ... pass - >>> class IPoultry(IAnimal): - ... pass - >>> class IChicken(IPoultry): - ... pass - >>> class ISeafood(IAnimal): - ... pass - -Adapting to some other interface for which there is no -subscription adapter returns an empty sequence:: - - >>> class IRecipe(zope.interface.Interface): - ... pass - >>> class ISausages(IRecipe): - ... pass - >>> class INoodles(IRecipe): - ... pass - >>> class IKFC(IRecipe): - ... pass - - >>> list(registry.subscriptions([IPoultry], IRecipe)) - [] - -unless we define a subscription:: - - >>> registry.subscribe([IAnimal], ISausages, 'sausages') - >>> list(registry.subscriptions([IPoultry], ISausages)) - ['sausages'] - -And define another subscription adapter:: - - >>> registry.subscribe([IPoultry], INoodles, 'noodles') - >>> meals = list(registry.subscriptions([IPoultry], IRecipe)) - >>> meals.sort() - >>> meals - ['noodles', 'sausages'] - - >>> registry.subscribe([IChicken], IKFC, 'kfc') - >>> meals = list(registry.subscriptions([IChicken], IRecipe)) - >>> meals.sort() - >>> meals - ['kfc', 'noodles', 'sausages'] - -And the answer for poultry hasn't changed:: - - >>> meals = list(registry.subscriptions([IPoultry], IRecipe)) - >>> meals.sort() - >>> meals - ['noodles', 'sausages'] diff --git a/src/zope/interface/tests/ifoo.py b/src/zope/interface/tests/ifoo.py deleted file mode 100644 index 6ae2231..0000000 --- a/src/zope/interface/tests/ifoo.py +++ /dev/null @@ -1,28 +0,0 @@ -############################################################################## -# -# Copyright (c) 2001, 2002 Zope Corporation 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. -# -############################################################################## -"""IFoo test module - -$Id$ -""" -from zope.interface import Interface - -class IFoo(Interface): - """ - Dummy interface for unit tests. - """ - - def bar(baz): - """ - Just a note. - """ diff --git a/src/zope/interface/tests/m1.py b/src/zope/interface/tests/m1.py deleted file mode 100644 index 86adad2..0000000 --- a/src/zope/interface/tests/m1.py +++ /dev/null @@ -1,23 +0,0 @@ -############################################################################## -# -# Copyright (c) 2004 Zope Corporation 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 module that declares an interface - -$Id$ -""" -from zope.interface import Interface, moduleProvides - -class I1(Interface): pass -class I2(Interface): pass - -moduleProvides(I1, I2) diff --git a/src/zope/interface/tests/m2.py b/src/zope/interface/tests/m2.py deleted file mode 100644 index 16762dd..0000000 --- a/src/zope/interface/tests/m2.py +++ /dev/null @@ -1,17 +0,0 @@ -############################################################################## -# -# Copyright (c) 2004 Zope Corporation 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 module that doesn't declare an interface - -$Id$ -""" diff --git a/src/zope/interface/tests/odd.py b/src/zope/interface/tests/odd.py deleted file mode 100644 index 6fc7905..0000000 --- a/src/zope/interface/tests/odd.py +++ /dev/null @@ -1,129 +0,0 @@ -############################################################################## -# -# Copyright (c) 2003 Zope Corporation 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. -# -############################################################################## -"""Odd meta class that doesn't subclass type. - -This is used for testing support for ExtensionClass in new interfaces. - - >>> class A(object): - ... __metaclass__ = MetaClass - ... a = 1 - ... - >>> A.__name__ - 'A' - >>> A.__bases__ - () - >>> class B(object): - ... __metaclass__ = MetaClass - ... b = 1 - ... - >>> class C(A, B): pass - ... - >>> C.__name__ - 'C' - >>> int(C.__bases__ == (A, B)) - 1 - >>> a = A() - >>> aa = A() - >>> a.a - 1 - >>> aa.a - 1 - >>> aa.a = 2 - >>> a.a - 1 - >>> aa.a - 2 - >>> c = C() - >>> c.a - 1 - >>> c.b - 1 - >>> c.b = 2 - >>> c.b - 2 - >>> C.c = 1 - >>> c.c - 1 - >>> from types import ClassType - >>> int(isinstance(C, (type, ClassType))) - 0 - >>> int(C.__class__.__class__ is C.__class__) - 1 - -$Id$ -""" - -# class OddClass is an odd meta class - -class MetaMetaClass(type): - - def __getattribute__(self, name): - if name == '__class__': - return self - return type.__getattribute__(self, name) - - -class MetaClass(object): - """Odd classes - """ - __metaclass__ = MetaMetaClass - - def __init__(self, name, bases, dict): - self.__name__ = name - self.__bases__ = bases - self.__dict__.update(dict) - - def __call__(self): - return OddInstance(self) - - def __getattr__(self, name): - for b in self.__bases__: - v = getattr(b, name, self) - if v is not self: - return v - raise AttributeError(name) - - def __repr__(self): - return "<odd class %s at %s>" % (self.__name__, hex(id(self))) - -class OddInstance(object): - - def __init__(self, cls): - self.__dict__['__class__'] = cls - - def __getattribute__(self, name): - dict = object.__getattribute__(self, '__dict__') - if name == '__dict__': - return dict - v = dict.get(name, self) - if v is not self: - return v - return getattr(dict['__class__'], name) - - def __setattr__(self, name, v): - self.__dict__[name] = v - - def __delattr__(self, name): - del self.__dict__[name] - - def __repr__(self): - return "<odd %s instance at %s>" % ( - self.__class__.__name__, hex(id(self))) - - - -# DocTest: -if __name__ == "__main__": - import doctest, __main__ - doctest.testmod(__main__, isprivate=lambda *a: False) diff --git a/src/zope/interface/tests/test_adapter.py b/src/zope/interface/tests/test_adapter.py deleted file mode 100644 index ed3fc69..0000000 --- a/src/zope/interface/tests/test_adapter.py +++ /dev/null @@ -1,336 +0,0 @@ -############################################################################## -# -# Copyright (c) 2003 Zope Corporation 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. -# -############################################################################## -"""Adapter registry tests - -$Id$ -""" -import unittest -import zope.interface -from zope.interface.adapter import AdapterRegistry -import zope.interface - -class IF0(zope.interface.Interface): - pass -class IF1(IF0): - pass - -class IB0(zope.interface.Interface): - pass -class IB1(IB0): - pass - -class IR0(zope.interface.Interface): - pass -class IR1(IR0): - pass - -def test_multi_adapter_get_best_match(): - """ - >>> registry = AdapterRegistry() - - >>> class IB2(IB0): - ... pass - >>> class IB3(IB2, IB1): - ... pass - >>> class IB4(IB1, IB2): - ... pass - - >>> registry.register([None, IB1], IR0, '', 'A1') - >>> registry.register([None, IB0], IR0, '', 'A0') - >>> registry.register([None, IB2], IR0, '', 'A2') - - >>> registry.lookup((IF1, IB1), IR0, '') - 'A1' - >>> registry.lookup((IF1, IB2), IR0, '') - 'A2' - >>> registry.lookup((IF1, IB0), IR0, '') - 'A0' - >>> registry.lookup((IF1, IB3), IR0, '') - 'A2' - >>> registry.lookup((IF1, IB4), IR0, '') - 'A1' - """ - -def test_multi_adapter_lookupAll_get_best_matches(): - """ - >>> registry = AdapterRegistry() - - >>> class IB2(IB0): - ... pass - >>> class IB3(IB2, IB1): - ... pass - >>> class IB4(IB1, IB2): - ... pass - - >>> registry.register([None, IB1], IR0, '', 'A1') - >>> registry.register([None, IB0], IR0, '', 'A0') - >>> registry.register([None, IB2], IR0, '', 'A2') - - >>> registry.lookupAll((IF1, IB1), IR0).next()[1] - 'A1' - >>> registry.lookupAll((IF1, IB2), IR0).next()[1] - 'A2' - >>> registry.lookupAll((IF1, IB0), IR0).next()[1] - 'A0' - >>> registry.lookupAll((IF1, IB3), IR0).next()[1] - 'A2' - >>> registry.lookupAll((IF1, IB4), IR0).next()[1] - 'A1' - """ - - -def test_multi_adapter_w_default(): - """ - >>> registry = AdapterRegistry() - - >>> registry.register([None, None], IB1, 'bob', 'A0') - - >>> registry.lookup((IF1, IR1), IB0, 'bob') - 'A0' - - >>> registry.register([None, IR0], IB1, 'bob', 'A1') - - >>> registry.lookup((IF1, IR1), IB0, 'bob') - 'A1' - - >>> registry.lookup((IF1, IR1), IB0, 'bruce') - - >>> registry.register([None, IR1], IB1, 'bob', 'A2') - >>> registry.lookup((IF1, IR1), IB0, 'bob') - 'A2' - """ - -def test_multi_adapter_w_inherited_and_multiple_registrations(): - """ - >>> registry = AdapterRegistry() - - >>> class IX(zope.interface.Interface): - ... pass - - >>> registry.register([IF0, IR0], IB1, 'bob', 'A1') - >>> registry.register([IF1, IX], IB1, 'bob', 'AX') - - >>> registry.lookup((IF1, IR1), IB0, 'bob') - 'A1' - """ - -def test_named_adapter_with_default(): - """Query a named simple adapter - - >>> registry = AdapterRegistry() - - If we ask for a named adapter, we won't get a result unless there - is a named adapter, even if the object implements the interface: - - >>> registry.lookup([IF1], IF0, 'bob') - - >>> registry.register([None], IB1, 'bob', 'A1') - >>> registry.lookup([IF1], IB0, 'bob') - 'A1' - - >>> registry.lookup([IF1], IB0, 'bruce') - - >>> registry.register([None], IB0, 'bob', 'A2') - >>> registry.lookup([IF1], IB0, 'bob') - 'A2' - """ - -def test_multi_adapter_gets_closest_provided(): - """ - >>> registry = AdapterRegistry() - >>> registry.register([IF1, IR0], IB0, 'bob', 'A1') - >>> registry.register((IF1, IR0), IB1, 'bob', 'A2') - >>> registry.lookup((IF1, IR1), IB0, 'bob') - 'A1' - - >>> registry = AdapterRegistry() - >>> registry.register([IF1, IR0], IB1, 'bob', 'A2') - >>> registry.register([IF1, IR0], IB0, 'bob', 'A1') - >>> registry.lookup([IF1, IR0], IB0, 'bob') - 'A1' - - >>> registry = AdapterRegistry() - >>> registry.register([IF1, IR0], IB0, 'bob', 'A1') - >>> registry.register([IF1, IR1], IB1, 'bob', 'A2') - >>> registry.lookup([IF1, IR1], IB0, 'bob') - 'A2' - - >>> registry = AdapterRegistry() - >>> registry.register([IF1, IR1], IB1, 'bob', 2) - >>> registry.register([IF1, IR0], IB0, 'bob', 1) - >>> registry.lookup([IF1, IR1], IB0, 'bob') - 2 - """ - -def test_multi_adapter_check_non_default_dont_hide_default(): - """ - >>> registry = AdapterRegistry() - - >>> class IX(zope.interface.Interface): - ... pass - - - >>> registry.register([None, IR0], IB0, 'bob', 1) - >>> registry.register([IF1, IX], IB0, 'bob', 2) - >>> registry.lookup([IF1, IR1], IB0, 'bob') - 1 - """ - -def test_adapter_hook_with_factory_producing_None(): - """ - >>> registry = AdapterRegistry() - >>> default = object() - - >>> class Object1(object): - ... zope.interface.implements(IF0) - >>> class Object2(object): - ... zope.interface.implements(IF0) - - >>> def factory(context): - ... if isinstance(context, Object1): - ... return 'adapter' - ... return None - - >>> registry.register([IF0], IB0, '', factory) - - >>> registry.adapter_hook(IB0, Object1()) - 'adapter' - >>> registry.adapter_hook(IB0, Object2()) is None - True - >>> registry.adapter_hook(IB0, Object2(), default=default) is default - True - """ - -def test_adapter_registry_update_upon_interface_bases_change(): - """ - Let's first create a adapter registry and a simple adaptation hook: - - >>> globalRegistry = AdapterRegistry() - - >>> def _hook(iface, ob, lookup=globalRegistry.lookup1): - ... factory = lookup(zope.interface.providedBy(ob), iface) - ... if factory is None: - ... return None - ... else: - ... return factory(ob) - - >>> zope.interface.interface.adapter_hooks.append(_hook) - - Now we create some interfaces and an implementation: - - >>> class IX(zope.interface.Interface): - ... pass - - >>> class IY(zope.interface.Interface): - ... pass - - >>> class X(object): - ... pass - - >>> class Y(object): - ... zope.interface.implements(IY) - ... def __init__(self, original): - ... self.original=original - - and register an adapter: - - >>> globalRegistry.register((IX,), IY, '', Y) - - at first, we still expect the adapter lookup from `X` to `IY` to fail: - - >>> IY(X()) #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS - Traceback (most recent call last): - ... - TypeError: ('Could not adapt', - <zope.interface.tests.test_adapter.X object at ...>, - <InterfaceClass zope.interface.tests.test_adapter.IY>) - - But after we declare an interface on the class `X`, it should pass: - - >>> zope.interface.classImplementsOnly(X, IX) - - >>> IY(X()) #doctest: +ELLIPSIS - <zope.interface.tests.test_adapter.Y object at ...> - - >>> hook = zope.interface.interface.adapter_hooks.pop() - """ - - -def test_changing_declarations(): - """ - - If we change declarations for a class, those adapter lookup should - eflect the changes: - - >>> class I1(zope.interface.Interface): - ... pass - >>> class I2(zope.interface.Interface): - ... pass - - >>> registry = AdapterRegistry() - >>> registry.register([I1], I2, '', 42) - - >>> class C: - ... pass - - >>> registry.lookup([zope.interface.implementedBy(C)], I2, '') - - >>> zope.interface.classImplements(C, I1) - - >>> registry.lookup([zope.interface.implementedBy(C)], I2, '') - 42 - """ - -def test_correct_multi_adapter_lookup(): - """ - >>> registry = AdapterRegistry() - >>> registry.register([IF0, IB1], IR0, '', 'A01') - >>> registry.register([IF1, IB0], IR0, '', 'A10') - >>> registry.lookup((IF1, IB1), IR0, '') - 'A10' - """ - -def test_duplicate_bases(): - """ -There was a bug that caused problems if a spec had multiple bases: - - >>> class I(zope.interface.Interface): - ... pass - >>> class I2(I, I): - ... pass - >>> registry = AdapterRegistry() - >>> registry.register([I2], IR0, 'x', 'X') - >>> registry.lookup((I2, ), IR0, 'x') - 'X' - >>> registry.register([I2], IR0, 'y', 'Y') - >>> registry.lookup((I2, ), IR0, 'x') - 'X' - >>> registry.lookup((I2, ), IR0, 'y') - 'Y' - - - -""" - -def test_suite(): - from zope.testing import doctest, doctestunit - return unittest.TestSuite(( - doctestunit.DocFileSuite('../adapter.txt', '../human.txt', - 'foodforthought.txt', - globs={'__name__': '__main__'}), - doctest.DocTestSuite(), - )) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff --git a/src/zope/interface/tests/test_advice.py b/src/zope/interface/tests/test_advice.py deleted file mode 100644 index ac96465..0000000 --- a/src/zope/interface/tests/test_advice.py +++ /dev/null @@ -1,178 +0,0 @@ - -############################################################################## -# -# Copyright (c) 2003 Zope Corporation 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. -# -############################################################################## -"""Tests for advice - -This module was adapted from 'protocols.tests.advice', part of the Python -Enterprise Application Kit (PEAK). Please notify the PEAK authors -(pje@telecommunity.com and tsarna@sarna.org) if bugs are found or -Zope-specific changes are required, so that the PEAK version of this module -can be kept in sync. - -PEAK is a Python application framework that interoperates with (but does -not require) Zope 3 and Twisted. It provides tools for manipulating UML -models, object-relational persistence, aspect-oriented programming, and more. -Visit the PEAK home page at http://peak.telecommunity.com for more information. - -$Id$ -""" - -import unittest -from unittest import TestCase, makeSuite, TestSuite -from zope.interface.advice import * -from types import ClassType -import sys - -def ping(log, value): - - def pong(klass): - log.append((value,klass)) - return [klass] - - addClassAdvisor(pong) - -class ClassicClass: - __metaclass__ = ClassType - classLevelFrameInfo = getFrameInfo(sys._getframe()) - -class NewStyleClass: - __metaclass__ = type - classLevelFrameInfo = getFrameInfo(sys._getframe()) - -moduleLevelFrameInfo = getFrameInfo(sys._getframe()) - -class FrameInfoTest(TestCase): - - classLevelFrameInfo = getFrameInfo(sys._getframe()) - - def checkModuleInfo(self): - kind, module, f_locals, f_globals = moduleLevelFrameInfo - self.assertEquals(kind, "module") - for d in module.__dict__, f_locals, f_globals: - self.assert_(d is globals()) - - def checkClassicClassInfo(self): - kind, module, f_locals, f_globals = ClassicClass.classLevelFrameInfo - self.assertEquals(kind, "class") - - self.assert_(f_locals is ClassicClass.__dict__) # ??? - for d in module.__dict__, f_globals: - self.assert_(d is globals()) - - def checkNewStyleClassInfo(self): - kind, module, f_locals, f_globals = NewStyleClass.classLevelFrameInfo - self.assertEquals(kind, "class") - - for d in module.__dict__, f_globals: - self.assert_(d is globals()) - - def checkCallInfo(self): - kind, module, f_locals, f_globals = getFrameInfo(sys._getframe()) - self.assertEquals(kind, "function call") - self.assert_(f_locals is locals()) # ??? - for d in module.__dict__, f_globals: - self.assert_(d is globals()) - - -class AdviceTests(TestCase): - - def checkOrder(self): - log = [] - class Foo(object): - ping(log, 1) - ping(log, 2) - ping(log, 3) - - # Strip the list nesting - for i in 1,2,3: - self.assert_(isinstance(Foo, list)) - Foo, = Foo - - self.assertEquals(log, [(1, Foo), (2, [Foo]), (3, [[Foo]])]) - - def TODOcheckOutside(self): - # Disabled because the check does not work with doctest tests. - try: - ping([], 1) - except SyntaxError: - pass - else: - raise AssertionError( - "Should have detected advice outside class body" - ) - - def checkDoubleType(self): - if sys.hexversion >= 0x02030000: - return # you can't duplicate bases in 2.3 - class aType(type,type): - ping([],1) - aType, = aType - self.assert_(aType.__class__ is type) - - def checkSingleExplicitMeta(self): - - class M(type): - pass - - class C(M): - __metaclass__ = M - ping([],1) - - C, = C - self.assert_(C.__class__ is M) - - - def checkMixedMetas(self): - - class M1(type): pass - class M2(type): pass - - class B1: __metaclass__ = M1 - class B2: __metaclass__ = M2 - - try: - class C(B1,B2): - ping([],1) - except TypeError: - pass - else: - raise AssertionError("Should have gotten incompatibility error") - - class M3(M1,M2): pass - - class C(B1,B2): - __metaclass__ = M3 - ping([],1) - - self.assert_(isinstance(C,list)) - C, = C - self.assert_(isinstance(C,M3)) - - def checkMetaOfClass(self): - - class metameta(type): - pass - - class meta(type): - __metaclass__ = metameta - - self.assertEquals(determineMetaclass((meta, type)), metameta) - -TestClasses = (AdviceTests, FrameInfoTest) - -def test_suite(): - return TestSuite([makeSuite(t,'check') for t in TestClasses]) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff --git a/src/zope/interface/tests/test_declarations.py b/src/zope/interface/tests/test_declarations.py deleted file mode 100644 index ac7523f..0000000 --- a/src/zope/interface/tests/test_declarations.py +++ /dev/null @@ -1,403 +0,0 @@ -############################################################################## -# -# Copyright (c) 2003 Zope Corporation 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 the new API for making and checking interface declarations - -$Id$ -""" -import unittest -from zope.interface import * -from zope.testing.doctestunit import DocTestSuite -from zope.interface import Interface - -class I1(Interface): pass -class I2(Interface): pass -class I3(Interface): pass -class I4(Interface): pass -class I5(Interface): pass - -class A(object): - implements(I1) -class B(object): - implements(I2) -class C(A, B): - implements(I3) - -class COnly(A, B): - implementsOnly(I3) - -class COnly_old(A, B): - __implemented__ = I3 - -class D(COnly): - implements(I5) - -def test_ObjectSpecification_Simple(): - """ - >>> c = C() - >>> directlyProvides(c, I4) - >>> [i.__name__ for i in providedBy(c)] - ['I4', 'I3', 'I1', 'I2'] - """ - -def test_ObjectSpecification_Simple_w_only(): - """ - >>> c = COnly() - >>> directlyProvides(c, I4) - >>> [i.__name__ for i in providedBy(c)] - ['I4', 'I3'] - """ - -def test_ObjectSpecification_Simple_old_style(): - """ - >>> c = COnly_old() - >>> directlyProvides(c, I4) - >>> [i.__name__ for i in providedBy(c)] - ['I4', 'I3'] - """ - - -class Test(unittest.TestCase): - - # Note that most of the tests are in the doc strings of the - # declarations module. - - def test_backward_compat(self): - - class C1(object): __implemented__ = I1 - class C2(C1): __implemented__ = I2, I5 - class C3(C2): __implemented__ = I3, C2.__implemented__ - - self.assert_(C3.__implemented__.__class__ is tuple) - - self.assertEqual( - [i.getName() for i in providedBy(C3())], - ['I3', 'I2', 'I5'], - ) - - class C4(C3): - implements(I4) - - self.assertEqual( - [i.getName() for i in providedBy(C4())], - ['I4', 'I3', 'I2', 'I5'], - ) - - self.assertEqual( - [i.getName() for i in C4.__implemented__], - ['I4', 'I3', 'I2', 'I5'], - ) - - # Note that C3.__implemented__ should now be a sequence of interfaces - self.assertEqual( - [i.getName() for i in C3.__implemented__], - ['I3', 'I2', 'I5'], - ) - self.failIf(C3.__implemented__.__class__ is tuple) - - def test_module(self): - import zope.interface.tests.m1 - import zope.interface.tests.m2 - directlyProvides(zope.interface.tests.m2, - zope.interface.tests.m1.I1, - zope.interface.tests.m1.I2, - ) - self.assertEqual(list(providedBy(zope.interface.tests.m1)), - list(providedBy(zope.interface.tests.m2)), - ) - - def test_builtins(self): - # Setup - - intspec = implementedBy(int) - olddeclared = intspec.declared - - classImplements(int, I1) - class myint(int): - implements(I2) - - x = 42 - self.assertEqual([i.getName() for i in providedBy(x)], - ['I1']) - - x = myint(42) - directlyProvides(x, I3) - self.assertEqual([i.getName() for i in providedBy(x)], - ['I3', 'I2', 'I1']) - - # cleanup - intspec.declared = olddeclared - classImplements(int) - - x = 42 - self.assertEqual([i.getName() for i in providedBy(x)], - []) - - -def test_signature_w_no_class_interfaces(): - """ - >>> from zope.interface import * - >>> class C(object): - ... pass - >>> c = C() - >>> list(providedBy(c)) - [] - - >>> class I(Interface): - ... pass - >>> directlyProvides(c, I) - >>> list(providedBy(c)) == list(directlyProvidedBy(c)) - 1 - """ - -def test_classImplement_on_deeply_nested_classes(): - """This test is in response to a bug found, which is why it's a bit - contrived - - >>> from zope.interface import * - >>> class B1(object): - ... pass - >>> class B2(B1): - ... pass - >>> class B3(B2): - ... pass - >>> class D(object): - ... implements() - >>> class S(B3, D): - ... implements() - - This failed due to a bug in the code for finding __providedBy__ - descriptors for old-style classes. - - """ - -def test_pickle_provides_specs(): - """ - >>> from pickle import dumps, loads - >>> a = A() - >>> I2.providedBy(a) - 0 - >>> directlyProvides(a, I2) - >>> I2.providedBy(a) - 1 - >>> a2 = loads(dumps(a)) - >>> I2.providedBy(a2) - 1 - - """ - -def test_that_we_dont_inherit_class_provides(): - """ - >>> class X(object): - ... classProvides(I1) - >>> class Y(X): - ... pass - >>> [i.__name__ for i in X.__provides__] - ['I1'] - >>> Y.__provides__ - Traceback (most recent call last): - ... - AttributeError: __provides__ - - """ - -def test_that_we_dont_inherit_provides_optimizations(): - """ - - When we make a declaration for a class, we install a __provides__ - descriptors that provides a default for instances that don't have - instance-specific declarations: - - >>> class A(object): - ... implements(I1) - - >>> class B(object): - ... implements(I2) - - >>> [i.__name__ for i in A().__provides__] - ['I1'] - >>> [i.__name__ for i in B().__provides__] - ['I2'] - - But it's important that we don't use this for subclasses without - declarations. This would cause incorrect results: - - >>> class X(A, B): - ... pass - - >>> X().__provides__ - Traceback (most recent call last): - ... - AttributeError: __provides__ - - However, if we "induce" a declaration, by calling implementedBy - (even indirectly through providedBy): - - >>> [i.__name__ for i in providedBy(X())] - ['I1', 'I2'] - - - then the optimization will work: - - >>> [i.__name__ for i in X().__provides__] - ['I1', 'I2'] - - """ - -def test_classProvides_before_implements(): - """Special descriptor for class __provides__ - - The descriptor caches the implementedBy info, so that - we can get declarations for objects without instance-specific - interfaces a bit quicker. - - For example:: - - >>> from zope.interface import Interface - >>> class IFooFactory(Interface): - ... pass - >>> class IFoo(Interface): - ... pass - >>> class C(object): - ... classProvides(IFooFactory) - ... implements(IFoo) - >>> [i.getName() for i in C.__provides__] - ['IFooFactory'] - - >>> [i.getName() for i in C().__provides__] - ['IFoo'] - """ - -def test_getting_spec_for_proxied_builtin_class(): - """ - - In general, we should be able to get a spec - for a proxied class if someone has declared or - asked for a spec before. - - We don't want to depend on proxies in this (zope.interface) - package, but we do want to work with proxies. Proxies have the - effect that a class's __dict__ cannot be gotten. Further, for - built-in classes, we can't save, and thus, cannot get, any class - attributes. We'll emulate this by treating a plain object as a class: - - >>> cls = object() - - We'll create an implements specification: - - >>> import zope.interface.declarations - >>> impl = zope.interface.declarations.Implements(I1, I2) - - Now, we'll emulate a declaration for a built-in type by putting - it in BuiltinImplementationSpecifications: - - >>> zope.interface.declarations.BuiltinImplementationSpecifications[ - ... cls] = impl - - Now, we should be able to get it back: - - >>> implementedBy(cls) is impl - True - - Of course, we don't want to leave it there. :) - - >>> del zope.interface.declarations.BuiltinImplementationSpecifications[ - ... cls] - - """ - -def test_declaration_get(): - """ - We can get definitions from a declaration: - - >>> import zope.interface - >>> class I1(zope.interface.Interface): - ... a11 = zope.interface.Attribute('a11') - ... a12 = zope.interface.Attribute('a12') - >>> class I2(zope.interface.Interface): - ... a21 = zope.interface.Attribute('a21') - ... a22 = zope.interface.Attribute('a22') - ... a12 = zope.interface.Attribute('a212') - >>> class I11(I1): - ... a11 = zope.interface.Attribute('a111') - - >>> decl = Declaration(I11, I2) - >>> decl.get('a11') is I11.get('a11') - True - >>> decl.get('a12') is I1.get('a12') - True - >>> decl.get('a21') is I2.get('a21') - True - >>> decl.get('a22') is I2.get('a22') - True - >>> decl.get('a') - >>> decl.get('a', 42) - 42 - - We get None even with no interfaces: - - >>> decl = Declaration() - >>> decl.get('a11') - >>> decl.get('a11', 42) - 42 - - We get new data if e change interface bases: - - >>> decl.__bases__ = I11, I2 - >>> decl.get('a11') is I11.get('a11') - True - """ - -def test_classImplements_after_classImplementsOnly_issue_402(): - """http://www.zope.org/Collectors/Zope3-dev/402 - ->>> from zope.interface import * ->>> class I1(Interface): -... pass ->>> class I2(Interface): -... pass ->>> class C: -... implements(I1) ->>> class C2: -... implementsOnly(I2) ->>> class I3(Interface): -... pass - ->>> [i.__name__ for i in providedBy(C2()).__iro__] -['I2', 'Interface'] - ->>> classImplements(C2, I3) ->>> [i.__name__ for i in providedBy(C2()).__iro__] -['I2', 'I3', 'Interface'] - ->>> class I4(Interface): -... pass ->>> classImplements(C2, I4) ->>> [i.__name__ for i in providedBy(C2()).__iro__] -['I2', 'I3', 'I4', 'Interface'] - - -""" - - -def test_suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(Test)) - suite.addTest(DocTestSuite("zope.interface.declarations")) - suite.addTest(DocTestSuite()) - - return suite - - -if __name__ == '__main__': - unittest.main() diff --git a/src/zope/interface/tests/test_document.py b/src/zope/interface/tests/test_document.py deleted file mode 100644 index 67648e3..0000000 --- a/src/zope/interface/tests/test_document.py +++ /dev/null @@ -1,71 +0,0 @@ -############################################################################## -# -# Copyright (c) 2001, 2002 Zope Corporation 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. -# -############################################################################## -"""Documentation tests. - -$Id$ -""" -from unittest import TestCase, main, makeSuite - -from zope.interface import Interface, Attribute - -class Test(TestCase): - - def testBlech(self): - from zope.interface.document import asStructuredText - - self.assertEqual(asStructuredText(I2), '''\ -I2 - - I2 doc - - This interface extends: - - o _I1 - - Attributes: - - a1 -- no documentation - - a2 -- a2 doc - - Methods: - - f21() -- f21 doc - - f22() -- no documentation - - f23() -- f23 doc - -''') - - -def test_suite(): - return makeSuite(Test) - -class _I1(Interface): - def f11(): pass - def f12(): pass - -class I2(_I1): - "I2 doc" - - a1 = Attribute('a1') - a2 = Attribute('a2', 'a2 doc') - - def f21(): "f21 doc" - def f22(): pass - def f23(): "f23 doc" - -if __name__=='__main__': - main(defaultTest='test_suite') diff --git a/src/zope/interface/tests/test_element.py b/src/zope/interface/tests/test_element.py deleted file mode 100644 index 07d56da..0000000 --- a/src/zope/interface/tests/test_element.py +++ /dev/null @@ -1,43 +0,0 @@ -############################################################################## -# -# Copyright (c) 2003 Zope Corporation 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 Element meta-class. - -$Id$ -""" - -import unittest -from zope.interface.interface import Element - -class TestElement(unittest.TestCase): - - def test_taggedValues(self): - """Test that we can update tagged values of more than one element - """ - - e1 = Element("foo") - e2 = Element("bar") - e1.setTaggedValue("x", 1) - e2.setTaggedValue("x", 2) - self.assertEqual(e1.getTaggedValue("x"), 1) - self.assertEqual(e2.getTaggedValue("x"), 2) - - -def test_suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestElement)) - return suite - - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff --git a/src/zope/interface/tests/test_interface.py b/src/zope/interface/tests/test_interface.py deleted file mode 100644 index ff624ec..0000000 --- a/src/zope/interface/tests/test_interface.py +++ /dev/null @@ -1,353 +0,0 @@ -############################################################################## -# -# Copyright (c) 2001, 2002 Zope Corporation 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 - -$Id$ -""" -import sys -import unittest -from zope.testing.doctestunit import DocTestSuite -from zope.interface.tests.unitfixtures import * # hehehe -from zope.interface.exceptions import BrokenImplementation, Invalid -from zope.interface import implementedBy, providedBy -from zope.interface import Interface, directlyProvides, Attribute -from zope import interface - -class InterfaceTests(unittest.TestCase): - - def testInterfaceSetOnAttributes(self): - self.assertEqual(FooInterface['foobar'].interface, - FooInterface) - self.assertEqual(FooInterface['aMethod'].interface, - FooInterface) - - def testClassImplements(self): - self.assert_(IC.implementedBy(C)) - - self.assert_(I1.implementedBy(A)) - self.assert_(I1.implementedBy(B)) - self.assert_(not I1.implementedBy(C)) - self.assert_(I1.implementedBy(D)) - self.assert_(I1.implementedBy(E)) - - self.assert_(not I2.implementedBy(A)) - self.assert_(I2.implementedBy(B)) - self.assert_(not I2.implementedBy(C)) - - # No longer after interfacegeddon - # self.assert_(not I2.implementedBy(D)) - - self.assert_(not I2.implementedBy(E)) - - def testUtil(self): - self.assert_(IC in implementedBy(C)) - self.assert_(I1 in implementedBy(A)) - self.assert_(not I1 in implementedBy(C)) - self.assert_(I2 in implementedBy(B)) - self.assert_(not I2 in implementedBy(C)) - - self.assert_(IC in providedBy(C())) - self.assert_(I1 in providedBy(A())) - self.assert_(not I1 in providedBy(C())) - self.assert_(I2 in providedBy(B())) - self.assert_(not I2 in providedBy(C())) - - - def testObjectImplements(self): - self.assert_(IC.providedBy(C())) - - self.assert_(I1.providedBy(A())) - self.assert_(I1.providedBy(B())) - self.assert_(not I1.providedBy(C())) - self.assert_(I1.providedBy(D())) - self.assert_(I1.providedBy(E())) - - self.assert_(not I2.providedBy(A())) - self.assert_(I2.providedBy(B())) - self.assert_(not I2.providedBy(C())) - - # Not after interface geddon - # self.assert_(not I2.providedBy(D())) - - self.assert_(not I2.providedBy(E())) - - def testDeferredClass(self): - a = A() - self.assertRaises(BrokenImplementation, a.ma) - - - def testInterfaceExtendsInterface(self): - self.assert_(BazInterface.extends(BobInterface)) - self.assert_(BazInterface.extends(BarInterface)) - self.assert_(BazInterface.extends(FunInterface)) - self.assert_(not BobInterface.extends(FunInterface)) - self.assert_(not BobInterface.extends(BarInterface)) - self.assert_(BarInterface.extends(FunInterface)) - self.assert_(not BarInterface.extends(BazInterface)) - - def testVerifyImplementation(self): - from zope.interface.verify import verifyClass - self.assert_(verifyClass(FooInterface, Foo)) - self.assert_(Interface.providedBy(I1)) - - def test_names(self): - names = list(_I2.names()); names.sort() - self.assertEqual(names, ['f21', 'f22', 'f23']) - names = list(_I2.names(all=True)); names.sort() - self.assertEqual(names, ['a1', 'f11', 'f12', 'f21', 'f22', 'f23']) - - def test_namesAndDescriptions(self): - names = [nd[0] for nd in _I2.namesAndDescriptions()]; names.sort() - self.assertEqual(names, ['f21', 'f22', 'f23']) - names = [nd[0] for nd in _I2.namesAndDescriptions(1)]; names.sort() - self.assertEqual(names, ['a1', 'f11', 'f12', 'f21', 'f22', 'f23']) - - for name, d in _I2.namesAndDescriptions(1): - self.assertEqual(name, d.__name__) - - def test_getDescriptionFor(self): - self.assertEqual(_I2.getDescriptionFor('f11').__name__, 'f11') - self.assertEqual(_I2.getDescriptionFor('f22').__name__, 'f22') - self.assertEqual(_I2.queryDescriptionFor('f33', self), self) - self.assertRaises(KeyError, _I2.getDescriptionFor, 'f33') - - def test___getitem__(self): - self.assertEqual(_I2['f11'].__name__, 'f11') - self.assertEqual(_I2['f22'].__name__, 'f22') - self.assertEqual(_I2.get('f33', self), self) - self.assertRaises(KeyError, _I2.__getitem__, 'f33') - - def test___contains__(self): - self.failUnless('f11' in _I2) - self.failIf('f33' in _I2) - - def test___iter__(self): - names = list(iter(_I2)) - names.sort() - self.assertEqual(names, ['a1', 'f11', 'f12', 'f21', 'f22', 'f23']) - - def testAttr(self): - description = _I2.getDescriptionFor('a1') - self.assertEqual(description.__name__, 'a1') - self.assertEqual(description.__doc__, 'This is an attribute') - - def testFunctionAttributes(self): - # Make sure function attributes become tagged values. - meth = _I1['f12'] - self.assertEqual(meth.getTaggedValue('optional'), 1) - - def testInvariant(self): - # set up - o = InvariantC() - directlyProvides(o, IInvariant) - # a helper - def errorsEqual(self, o, error_len, error_msgs, interface=None): - if interface is None: - interface = IInvariant - self.assertRaises(Invalid, interface.validateInvariants, o) - e = [] - try: - interface.validateInvariants(o, e) - except Invalid, error: - self.assertEquals(error.args[0], e) - else: - self._assert(0) # validateInvariants should always raise - # Invalid - self.assertEquals(len(e), error_len) - msgs = [error.args[0] for error in e] - msgs.sort() - for msg in msgs: - self.assertEquals(msg, error_msgs.pop(0)) - # the tests - self.assertEquals(IInvariant.getTaggedValue('invariants'), - [ifFooThenBar]) - self.assertEquals(IInvariant.validateInvariants(o), None) - o.bar = 27 - self.assertEquals(IInvariant.validateInvariants(o), None) - o.foo = 42 - self.assertEquals(IInvariant.validateInvariants(o), None) - del o.bar - errorsEqual(self, o, 1, ['If Foo, then Bar!']) - # nested interfaces with invariants: - self.assertEquals(ISubInvariant.getTaggedValue('invariants'), - [BarGreaterThanFoo]) - o = InvariantC() - directlyProvides(o, ISubInvariant) - o.foo = 42 - # even though the interface has changed, we should still only have one - # error. - errorsEqual(self, o, 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 - o.foo = 2 - o.bar = 1 - errorsEqual(self, o, 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! - o.foo = 1 - o.bar = 0 - errorsEqual(self, o, 2, ['If Foo, then Bar!', - 'Please, Boo MUST be greater than Foo!'], - ISubInvariant) - # for a happy ending, we'll make the invariants happy - o.foo = 1 - o.bar = 2 - self.assertEquals(IInvariant.validateInvariants(o), None) # woohoo - # 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. - o = InvariantC() - directlyProvides(o, IInvariant) - o.foo = 42 - old_invariants = IInvariant.getTaggedValue('invariants') - invariants = old_invariants[:] - invariants.append(BarGreaterThanFoo) # if you really need to mutate, - # then this would be the way to do it. Probably a bad idea, though. :-) - IInvariant.setTaggedValue('invariants', invariants) - # - # even though the interface has changed, we should still only have one - # error. - errorsEqual(self, o, 1, ['If Foo, then Bar!']) - # however, if we set foo to 0 (Boolean False) and bar to a negative - # number then we'll get the new error - o.foo = 2 - o.bar = 1 - errorsEqual(self, o, 1, ['Please, Boo MUST be greater than Foo!']) - # and if we set foo to a positive number and boo to 0, we'll - # get both errors! - o.foo = 1 - o.bar = 0 - errorsEqual(self, o, 2, ['If Foo, then Bar!', - 'Please, Boo MUST be greater than Foo!']) - # for another happy ending, we'll make the invariants happy again - o.foo = 1 - o.bar = 2 - self.assertEquals(IInvariant.validateInvariants(o), None) # bliss - # clean up - IInvariant.setTaggedValue('invariants', old_invariants) - - def test___doc___element(self): - class I(Interface): - "xxx" - - self.assertEqual(I.__doc__, "xxx") - self.assertEqual(list(I), []) - - class I(Interface): - "xxx" - - __doc__ = Attribute('the doc') - - self.assertEqual(I.__doc__, "") - self.assertEqual(list(I), ['__doc__']) - - def testIssue228(self): - # Test for http://collector.zope.org/Zope3-dev/228 - class I(Interface): - "xxx" - class Bad: - __providedBy__ = None - # Old style classes don't have a '__class__' attribute - self.failUnlessRaises(AttributeError, I.providedBy, Bad) - - -class _I1(Interface): - - a1 = Attribute("This is an attribute") - - def f11(): pass - def f12(): pass - f12.optional = 1 - -class _I1_(_I1): pass -class _I1__(_I1_): pass - -class _I2(_I1__): - def f21(): pass - def f22(): pass - f23 = f22 - - - -if sys.version_info >= (2, 4): - def test_invariant_as_decorator(): - """Invaiants can be deined in line - - >>> class IRange(interface.Interface): - ... min = interface.Attribute("Lower bound") - ... max = interface.Attribute("Upper bound") - ... - ... @interface.invariant - ... def range_invariant(ob): - ... if ob.max < ob.min: - ... raise Invalid('max < min') - - - >>> class Range(object): - ... interface.implements(IRange) - ... - ... def __init__(self, min, max): - ... self.min, self.max = min, max - - >>> IRange.validateInvariants(Range(1,2)) - >>> IRange.validateInvariants(Range(1,1)) - >>> IRange.validateInvariants(Range(2,1)) - Traceback (most recent call last): - ... - Invalid: max < min - - - """ - -def duplicate_bases_management(): - """ -There was a bug that surfaced when an interface was repeated in -a set of bases and the bases were changed: - - >>> class I(interface.Interface): - ... pass - - >>> class I2(I, I): - ... pass - - >>> I2.__bases__ = (I,) - - -""" - - -def test_suite(): - from zope.testing import doctest - suite = unittest.makeSuite(InterfaceTests) - suite.addTest(doctest.DocTestSuite("zope.interface.interface")) - if sys.version_info >= (2, 4): - suite.addTest(doctest.DocTestSuite()) - suite.addTest(doctest.DocFileSuite( - '../README.txt', - globs={'__name__': '__main__'}, - optionflags=doctest.NORMALIZE_WHITESPACE, - )) - suite.addTest(doctest.DocFileSuite( - '../README.ru.txt', - globs={'__name__': '__main__'}, - optionflags=doctest.NORMALIZE_WHITESPACE, - )) - return suite - -def main(): - unittest.TextTestRunner().run(test_suite()) - -if __name__=="__main__": - main() diff --git a/src/zope/interface/tests/test_odd_declarations.py b/src/zope/interface/tests/test_odd_declarations.py deleted file mode 100644 index 9b437d3..0000000 --- a/src/zope/interface/tests/test_odd_declarations.py +++ /dev/null @@ -1,204 +0,0 @@ -############################################################################## -# -# Copyright (c) 2003 Zope Corporation 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 declarations against ExtensionClass-like classes. - -These tests are to make sure we do something sane in the presense of -classic ExtensionClass classes and instances. - -$Id$ -""" -import unittest, odd -from zope.interface import Interface, implements, implementsOnly -from zope.interface import directlyProvides, providedBy, directlyProvidedBy -from zope.interface import classImplements, classImplementsOnly, implementedBy - -class I1(Interface): pass -class I2(Interface): pass -class I3(Interface): pass -class I31(I3): pass -class I4(Interface): pass -class I5(Interface): pass - -class Odd(object): __metaclass__ = odd.MetaClass - -class B(Odd): __implemented__ = I2 - - -# TODO: We are going to need more magic to make classProvides work with odd -# classes. This will work in the next iteration. For now, we'll use -# a different mechanism. - -# from zope.interface import classProvides - -class A(Odd): - implements(I1) - -class C(A, B): - implements(I31) - - -class Test(unittest.TestCase): - - def test_ObjectSpecification(self): - c = C() - directlyProvides(c, I4) - self.assertEqual([i.getName() for i in providedBy(c)], - ['I4', 'I31', 'I1', 'I2'] - ) - self.assertEqual([i.getName() for i in providedBy(c).flattened()], - ['I4', 'I31', 'I3', 'I1', 'I2', 'Interface'] - ) - self.assert_(I1 in providedBy(c)) - self.failIf(I3 in providedBy(c)) - self.assert_(providedBy(c).extends(I3)) - self.assert_(providedBy(c).extends(I31)) - self.failIf(providedBy(c).extends(I5)) - - class COnly(A, B): - implementsOnly(I31) - - class D(COnly): - implements(I5) - - classImplements(D, I5) - - c = D() - directlyProvides(c, I4) - self.assertEqual([i.getName() for i in providedBy(c)], - ['I4', 'I5', 'I31']) - self.assertEqual([i.getName() for i in providedBy(c).flattened()], - ['I4', 'I5', 'I31', 'I3', 'Interface']) - self.failIf(I1 in providedBy(c)) - self.failIf(I3 in providedBy(c)) - self.assert_(providedBy(c).extends(I3)) - self.failIf(providedBy(c).extends(I1)) - self.assert_(providedBy(c).extends(I31)) - self.assert_(providedBy(c).extends(I5)) - - class COnly(A, B): __implemented__ = I31 - class D(COnly): - implements(I5) - - classImplements(D, I5) - c = D() - directlyProvides(c, I4) - self.assertEqual([i.getName() for i in providedBy(c)], - ['I4', 'I5', 'I31']) - self.assertEqual([i.getName() for i in providedBy(c).flattened()], - ['I4', 'I5', 'I31', 'I3', 'Interface']) - self.failIf(I1 in providedBy(c)) - self.failIf(I3 in providedBy(c)) - self.assert_(providedBy(c).extends(I3)) - self.failIf(providedBy(c).extends(I1)) - self.assert_(providedBy(c).extends(I31)) - self.assert_(providedBy(c).extends(I5)) - - def test_classImplements(self): - class A(Odd): - implements(I3) - - class B(Odd): - implements(I4) - - class C(A, B): - pass - classImplements(C, I1, I2) - self.assertEqual([i.getName() for i in implementedBy(C)], - ['I1', 'I2', 'I3', 'I4']) - classImplements(C, I5) - self.assertEqual([i.getName() for i in implementedBy(C)], - ['I1', 'I2', 'I5', 'I3', 'I4']) - - def test_classImplementsOnly(self): - class A(Odd): - implements(I3) - - class B(Odd): - implements(I4) - - class C(A, B): - pass - classImplementsOnly(C, I1, I2) - self.assertEqual([i.__name__ for i in implementedBy(C)], - ['I1', 'I2']) - - - def test_directlyProvides(self): - class IA1(Interface): pass - class IA2(Interface): pass - class IB(Interface): pass - class IC(Interface): pass - class A(Odd): - implements(IA1, IA2) - - class B(Odd): - implements(IB) - - class C(A, B): - implements(IC) - - - ob = C() - directlyProvides(ob, I1, I2) - self.assert_(I1 in providedBy(ob)) - self.assert_(I2 in providedBy(ob)) - self.assert_(IA1 in providedBy(ob)) - self.assert_(IA2 in providedBy(ob)) - self.assert_(IB in providedBy(ob)) - self.assert_(IC in providedBy(ob)) - - directlyProvides(ob, directlyProvidedBy(ob)-I2) - self.assert_(I1 in providedBy(ob)) - self.failIf(I2 in providedBy(ob)) - self.failIf(I2 in providedBy(ob)) - directlyProvides(ob, directlyProvidedBy(ob), I2) - self.assert_(I2 in providedBy(ob)) - - def test_directlyProvides_fails_for_odd_class(self): - self.assertRaises(TypeError, directlyProvides, C, I5) - - # see above - def TODO_test_classProvides_fails_for_odd_class(self): - try: - class A(Odd): - classProvides(I1) - except TypeError: - pass # Sucess - self.assert_(False, - "Shouldn't be able to use directlyProvides on odd class." - ) - - def test_implementedBy(self): - class I2(I1): pass - - class C1(Odd): - implements(I2) - - class C2(C1): - implements(I3) - - self.assertEqual([i.getName() for i in implementedBy(C2)], - ['I3', 'I2']) - - - - -def test_suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(Test)) - return suite - - -if __name__ == '__main__': - unittest.main() diff --git a/src/zope/interface/tests/test_sorting.py b/src/zope/interface/tests/test_sorting.py deleted file mode 100644 index 31f575d..0000000 --- a/src/zope/interface/tests/test_sorting.py +++ /dev/null @@ -1,49 +0,0 @@ -############################################################################## -# -# Copyright (c) 2001, 2002 Zope Corporation 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 sorting - -$Id$ -""" - -from unittest import TestCase, TestSuite, main, makeSuite - -from zope.interface import Interface - -class I1(Interface): pass -class I2(I1): pass -class I3(I1): pass -class I4(Interface): pass -class I5(I4): pass -class I6(I2): pass - - -class Test(TestCase): - - def test(self): - l = [I1, I3, I5, I6, I4, I2] - l.sort() - self.assertEqual(l, [I1, I2, I3, I4, I5, I6]) - - def test_w_None(self): - l = [I1, None, I3, I5, None, I6, I4, I2] - l.sort() - self.assertEqual(l, [I1, I2, I3, I4, I5, I6, None, None]) - -def test_suite(): - return TestSuite(( - makeSuite(Test), - )) - -if __name__=='__main__': - main(defaultTest='test_suite') diff --git a/src/zope/interface/tests/test_verify.py b/src/zope/interface/tests/test_verify.py deleted file mode 100644 index d7f583b..0000000 --- a/src/zope/interface/tests/test_verify.py +++ /dev/null @@ -1,196 +0,0 @@ -############################################################################## -# -# Copyright (c) 2001, 2002 Zope Corporation 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. -# -############################################################################## -"""Interface Verify tests - -$Id$ -""" -from zope.interface import Interface, implements, classImplements, Attribute -from zope.interface.verify import verifyClass, verifyObject -from zope.interface.exceptions import DoesNotImplement, BrokenImplementation -from zope.interface.exceptions import BrokenMethodImplementation - -import unittest - -class Test(unittest.TestCase): - - def testNotImplemented(self): - - class C(object): pass - - class I(Interface): pass - - self.assertRaises(DoesNotImplement, verifyClass, I, C) - - classImplements(C, I) - - verifyClass(I, C) - - def testMissingAttr(self): - - class I(Interface): - def f(): pass - - class C(object): - implements(I) - - self.assertRaises(BrokenImplementation, verifyClass, I, C) - - C.f=lambda self: None - - verifyClass(I, C) - - def testMissingAttr_with_Extended_Interface(self): - - class II(Interface): - def f(): - pass - - class I(II): - pass - - class C(object): - implements(I) - - self.assertRaises(BrokenImplementation, verifyClass, I, C) - - C.f=lambda self: None - - verifyClass(I, C) - - def testWrongArgs(self): - - class I(Interface): - def f(a): pass - - class C(object): - def f(self, b): pass - - implements(I) - - # We no longer require names to match. - #self.assertRaises(BrokenMethodImplementation, verifyClass, I, C) - - C.f=lambda self, a: None - - verifyClass(I, C) - - C.f=lambda self, **kw: None - - self.assertRaises(BrokenMethodImplementation, verifyClass, I, C) - - C.f=lambda self, a, *args: None - - verifyClass(I, C) - - C.f=lambda self, a, *args, **kw: None - - verifyClass(I, C) - - C.f=lambda self, *args: None - - verifyClass(I, C) - - def testExtraArgs(self): - - class I(Interface): - def f(a): pass - - class C(object): - def f(self, a, b): pass - - implements(I) - - self.assertRaises(BrokenMethodImplementation, verifyClass, I, C) - - C.f=lambda self, a: None - - verifyClass(I, C) - - C.f=lambda self, a, b=None: None - - verifyClass(I, C) - - def testNoVar(self): - - class I(Interface): - def f(a, *args): pass - - class C(object): - def f(self, a): pass - - implements(I) - - self.assertRaises(BrokenMethodImplementation, verifyClass, I, C) - - C.f=lambda self, a, *foo: None - - verifyClass(I, C) - - def testNoKW(self): - - class I(Interface): - def f(a, **args): pass - - class C(object): - def f(self, a): pass - - implements(I) - - self.assertRaises(BrokenMethodImplementation, verifyClass, I, C) - - C.f=lambda self, a, **foo: None - - verifyClass(I, C) - - def testModule(self): - - from zope.interface.tests.ifoo import IFoo - from zope.interface.tests import dummy - - verifyObject(IFoo, dummy) - - def testMethodForAttr(self): - - class IFoo(Interface): - foo = Attribute("The foo Attribute") - - - class Foo: - implements(IFoo) - - def foo(self): - pass - - verifyClass(IFoo, Foo) - - def testNonMethodForMethod(self): - - class IBar(Interface): - def foo(): - pass - - class Bar: - implements(IBar) - - foo = 1 - - self.assertRaises(BrokenMethodImplementation, verifyClass, IBar, Bar) - - -def test_suite(): - loader=unittest.TestLoader() - return loader.loadTestsFromTestCase(Test) - -if __name__=='__main__': - unittest.TextTestRunner().run(test_suite()) diff --git a/src/zope/interface/tests/unitfixtures.py b/src/zope/interface/tests/unitfixtures.py deleted file mode 100644 index bdd697c..0000000 --- a/src/zope/interface/tests/unitfixtures.py +++ /dev/null @@ -1,142 +0,0 @@ -############################################################################## -# -# Copyright (c) 2001, 2002 Zope Corporation 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. -# -############################################################################## -"""Unit Test Fixtures - -$Id$ -""" -from zope.interface import Interface, invariant -from zope.interface.interface import Attribute -from zope.interface.exceptions import Invalid - -class mytest(Interface): - pass - -class C(object): - def m1(self, a, b): - "return 1" - return 1 - - def m2(self, a, b): - "return 2" - return 2 - -# testInstancesOfClassImplements - -# YAGNI IC=Interface.impliedInterface(C) -class IC(Interface): - def m1(a, b): - "return 1" - - def m2(a, b): - "return 2" - - - -C.__implemented__=IC - -class I1(Interface): - def ma(): - "blah" - -class I2(I1): pass - -class I3(Interface): pass - -class I4(Interface): pass - -class A(I1.deferred()): - __implemented__=I1 - -class B(object): - __implemented__=I2, I3 - -class D(A, B): pass - -class E(A, B): - __implemented__ = A.__implemented__, C.__implemented__ - - -class FooInterface(Interface): - """ This is an Abstract Base Class """ - - foobar = Attribute("fuzzed over beyond all recognition") - - def aMethod(foo, bar, bingo): - """ This is aMethod """ - - def anotherMethod(foo=6, bar="where you get sloshed", bingo=(1,3,)): - """ This is anotherMethod """ - - def wammy(zip, *argues): - """ yadda yadda """ - - def useless(**keywords): - """ useless code is fun! """ - -class Foo(object): - """ A concrete class """ - - __implemented__ = FooInterface, - - foobar = "yeah" - - def aMethod(self, foo, bar, bingo): - """ This is aMethod """ - return "barf!" - - def anotherMethod(self, foo=6, bar="where you get sloshed", bingo=(1,3,)): - """ This is anotherMethod """ - return "barf!" - - def wammy(self, zip, *argues): - """ yadda yadda """ - return "barf!" - - def useless(self, **keywords): - """ useless code is fun! """ - return "barf!" - -foo_instance = Foo() - -class Blah(object): - pass - -new = Interface.__class__ -FunInterface = new('FunInterface') -BarInterface = new('BarInterface', [FunInterface]) -BobInterface = new('BobInterface') -BazInterface = new('BazInterface', [BobInterface, BarInterface]) - -# fixtures for invariant tests -def ifFooThenBar(obj): - if getattr(obj, 'foo', None) and not getattr(obj, 'bar', None): - raise Invalid('If Foo, then Bar!') -class IInvariant(Interface): - foo = Attribute('foo') - bar = Attribute('bar; must eval to Boolean True if foo does') - invariant(ifFooThenBar) -def BarGreaterThanFoo(obj): - 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!') -class ISubInvariant(IInvariant): - invariant(BarGreaterThanFoo) -class InvariantC(object): - pass diff --git a/src/zope/interface/verify.py b/src/zope/interface/verify.py deleted file mode 100644 index 60eb7ea..0000000 --- a/src/zope/interface/verify.py +++ /dev/null @@ -1,111 +0,0 @@ -############################################################################## -# -# Copyright (c) 2001, 2002 Zope Corporation 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. -# -############################################################################## -"""Verify interface implementations - -$Id$ -""" -from zope.interface.exceptions import BrokenImplementation, DoesNotImplement -from zope.interface.exceptions import BrokenMethodImplementation -from types import FunctionType, MethodType -from zope.interface.interface import fromMethod, fromFunction, Method - -# This will be monkey-patched when running under Zope 2, so leave this -# here: -MethodTypes = (MethodType, ) - - -def _verify(iface, candidate, tentative=0, vtype=None): - """Verify that 'candidate' might correctly implements 'iface'. - - This involves: - - o Making sure the candidate defines all the necessary methods - - o Making sure the methods have the correct signature - - o Making sure the candidate asserts that it implements the interface - - Note that this isn't the same as verifying that the class does - implement the interface. - - If optional tentative is true, suppress the "is implemented by" test. - """ - - if vtype == 'c': - tester = iface.implementedBy - else: - tester = iface.providedBy - - if not tentative and not tester(candidate): - raise DoesNotImplement(iface) - - # Here the `desc` is either an `Attribute` or `Method` instance - for name, desc in iface.namesAndDescriptions(1): - if not hasattr(candidate, name): - if (not isinstance(desc, Method)) and vtype == 'c': - # We can't verify non-methods on classes, since the - # class may provide attrs in it's __init__. - continue - - raise BrokenImplementation(iface, name) - - attr = getattr(candidate, name) - if not isinstance(desc, Method): - # If it's not a method, there's nothing else we can test - continue - - if isinstance(attr, FunctionType): - # should never get here, since classes should not provide functions - meth = fromFunction(attr, iface, name=name) - elif (isinstance(attr, MethodTypes) - and type(attr.im_func) is FunctionType): - meth = fromMethod(attr, iface, name) - else: - if not callable(attr): - raise BrokenMethodImplementation(name, "Not a method") - # sigh, it's callable, but we don't know how to intrspect it, so - # we have to give it a pass. - continue - - # Make sure that the required and implemented method signatures are - # the same. - desc = desc.getSignatureInfo() - meth = meth.getSignatureInfo() - - mess = _incompat(desc, meth) - if mess: - raise BrokenMethodImplementation(name, mess) - - return True - -def verifyClass(iface, candidate, tentative=0): - return _verify(iface, candidate, tentative, vtype='c') - -def verifyObject(iface, candidate, tentative=0): - return _verify(iface, candidate, tentative, vtype='o') - -def _incompat(required, implemented): - #if (required['positional'] != - # implemented['positional'][:len(required['positional'])] - # and implemented['kwargs'] is None): - # return 'imlementation has different argument names' - if len(implemented['required']) > len(required['required']): - return 'implementation requires too many arguments' - if ((len(implemented['positional']) < len(required['positional'])) - and not implemented['varargs']): - return "implementation doesn't allow enough arguments" - if required['kwargs'] and not implemented['kwargs']: - return "implementation doesn't support keyword arguments" - if required['varargs'] and not implemented['varargs']: - return "implementation doesn't support variable arguments" |
