SlideShare a Scribd company logo
1 of 22
Download to read offline
Zope Component
Architecture
There should be a silver bullet! Let's try to
look for it with ZCA at least :)
Anatoly Bubenkov
@bubenkoff
Paylogic Groningen Office
19.08.2013
I you’ve heard something bad about
zope...
Then probably you don’t know what it is :) So i’ll
tell you:
ZOPE stands for The Object Publising
Environment, so TOPE, but T -> Z to be polite.
Name zope itself is a fish, Ballerus ballerus,
also known as zope or blue bream, is a fish
native to Eurasia.
Some people say that python became popular
in web development because of zope :)
So what is zope?
Object-oriented web application server and framework
two main versions alive and actively developed:
zope2 - mainly known because Plone CMF is based on
it
zope3, then BlueBream, then part of BlueBream
became Zope Toolkit (ZTK).
Many things from zope3 were backported to zope2, but
zope3 is initially a full rewrite of zope2 using
Component Architecture.
And probably you’ve heard most of bad things about
zope2.
Component based architecture
Basically the idea:
● objects(components) interact only through interfaces.
● single interface - various implementations possible.
But interaction only through
interfaces can be tricky...
class ISize(Interface):
“””Object size.”””
size = Interface.Attribute(‘size’)
--------------------component---------------------------
class IDocument(Interface):
“””Text document.”””
text = Interface.Attribute(‘text’)
--------------------component---------------------------
class IImage(Interface):
“””Image.”””
image = Interface.Attribute(‘image’)
--------------------component---------------------------
To get size from objects of various types, we need to implement ISize, but if we
want to keep components separate, we can’t do it.
So here comes an Adapter paradigm
Adding adaptors, leads by-interface communication much more elegant, because you can control the
interaction between objects through them without direct modification.
IDocument -> ISize adaptor
ISize
IDocument IImage
IImage -> ISize adaptor
What do we have in python?
● PEP 246 (adaptation) and PEP 245
(interfaces) - killed by Guido in favor of
__notimplemented__
● zope.interface
● PyProtocols (not active since 2003)
● PEAK-Rules (allows you to HACK
everything,
so not a direct alternative, also seems not
active already)
zope.interface, here is the
implementation
The key package of:
● zope
● twisted
● pyramid
even Shipped out of the box with OSX :)
Pythonic (with C optimizations) implementation
of component architechture.
● python3 ready
● pypy compliant
zope.interface: 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"""
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'
Interfaces can inherit from each other just like normal python classes.
zope.interface: Interface
implementation
The most common way to declare interfaces is using the implements function in a class statement:
>>> class Foo(object):
... 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
We can ask if interface is implemented by class:
>>> IFoo.implementedBy(Foo)
True
Interface will be Provided by object, if it’s class implements it:
>>> foo = Foo()
>>> IFoo.providedBy(foo)
True
And of course interface is not provided by a class implementing it
>>> IFoo.providedBy(Foo)
False
But it’s also possible to dynamically provide interface for an object via zope.interface.directlyProvides
zope.interface: Invariants
Invariants are validation expressions, where input is only depends on interface attributes.
>>> 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(2,1))
Traceback (most recent call last):
...
RangeError: Range(2, 1)
zope.interface: Adapters
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
Finding out what, if anything, is registered
We can ask if there is an adapter registered for a collection of interfaces. This is
different than lookup, because it looks for an exact match:
>>> print registry.registered([IR1], IP1)
11
>>> print registry.registered([IR1], IP2)
12
>>> print registry.registered([IR1], IP2, 'bob')
Bob's 12
>>> print registry.registered([IR2], IP1)
21
>>> print registry.registered([IR2], IP2)
None
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
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
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()
>>> assert 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()
>>> assert adapters == [(u'', '1q22'), (u'bob', '1q2 for bob')]
zope.interface: 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.
You can have multiple subscribers for the same specification:
>>> registry.subscribe([IR1], IP2, 'sub12 2')
>>> registry.subscriptions([IR1], IP2)
['sub12 1', 'sub12 2']
If subscribers are registered for the same required interfaces, they are returned in the order of
definition.
You can register subscribers for all specifications using None:
>>> registry.subscribe([None], IP1, 'sub_1')
>>> registry.subscriptions([IR2], IP1)
['sub_1', 'sub12 1', 'sub12 2']
zope.interface: 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
zope.interface: 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
Where it can be used?
Basically in every ‘big and complex’ project.
Providing a clear communication protocol for
pieces of your big picture.
Adaptors are great when you need a
representation, for example a web-based view
of an object.
Handlers provide efficient event model.
Interfaces give you contracts.
..And why?
● Having system of many independent
components interacting via robust protocol is
much better than monolithic approach when
everyone knows everyone
● No need to invent the wheel (having api.py
in each of your package)
● Relying on python imports potentially causes
problems with circular dependencies, with
zope.interface you only need interfaces (can
be separate) for communication.
Thanks! Questions?
Reference:
● http://docs.zope.org/zope.interface/
● http://docs.zope.org/zope.component/
● http://www.muthukadan.net/docs/zca.html
● http://en.wikipedia.org/wiki/Zope
● http://en.wikipedia.
org/wiki/Design_by_contract
● http://www.artima.com/weblogs/viewpost.
jsp?thread=155123

More Related Content

Similar to Zope component architechture

JIT compilation for CPython
JIT compilation for CPythonJIT compilation for CPython
JIT compilation for CPythondelimitry
 
Talk - Query monad
Talk - Query monad Talk - Query monad
Talk - Query monad Fabernovel
 
Frege - consequently functional programming for the JVM
Frege - consequently functional programming for the JVMFrege - consequently functional programming for the JVM
Frege - consequently functional programming for the JVMDierk König
 
Introduction to Python 01-08-2023.pon by everyone else. . Hence, they must be...
Introduction to Python 01-08-2023.pon by everyone else. . Hence, they must be...Introduction to Python 01-08-2023.pon by everyone else. . Hence, they must be...
Introduction to Python 01-08-2023.pon by everyone else. . Hence, they must be...DRVaibhavmeshram1
 
Of Harmony and Stinginess: Applicative, Monad, and iterative library design
Of Harmony and Stinginess: Applicative, Monad, and iterative library designOf Harmony and Stinginess: Applicative, Monad, and iterative library design
Of Harmony and Stinginess: Applicative, Monad, and iterative library designjspha
 
掀起 Swift 的面紗
掀起 Swift 的面紗掀起 Swift 的面紗
掀起 Swift 的面紗Pofat Tseng
 
Writing Redis in Python with asyncio
Writing Redis in Python with asyncioWriting Redis in Python with asyncio
Writing Redis in Python with asyncioJames Saryerwinnie
 
Hierarchical free monads and software design in fp
Hierarchical free monads and software design in fpHierarchical free monads and software design in fp
Hierarchical free monads and software design in fpAlexander Granin
 
DjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New RelicDjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New RelicGraham Dumpleton
 
Djangocon11: Monkeying around at New Relic
Djangocon11: Monkeying around at New RelicDjangocon11: Monkeying around at New Relic
Djangocon11: Monkeying around at New RelicNew Relic
 
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...Ruby Meditation
 
Notes5
Notes5Notes5
Notes5hccit
 
Gevent what's the point
Gevent what's the pointGevent what's the point
Gevent what's the pointseanmcq
 
10 reasons to adopt Python 3
10 reasons to adopt Python 310 reasons to adopt Python 3
10 reasons to adopt Python 3Bleemeo
 

Similar to Zope component architechture (20)

Functional python
Functional pythonFunctional python
Functional python
 
JIT compilation for CPython
JIT compilation for CPythonJIT compilation for CPython
JIT compilation for CPython
 
Talk - Query monad
Talk - Query monad Talk - Query monad
Talk - Query monad
 
Frege - consequently functional programming for the JVM
Frege - consequently functional programming for the JVMFrege - consequently functional programming for the JVM
Frege - consequently functional programming for the JVM
 
Introduction to Python 01-08-2023.pon by everyone else. . Hence, they must be...
Introduction to Python 01-08-2023.pon by everyone else. . Hence, they must be...Introduction to Python 01-08-2023.pon by everyone else. . Hence, they must be...
Introduction to Python 01-08-2023.pon by everyone else. . Hence, they must be...
 
Of Harmony and Stinginess: Applicative, Monad, and iterative library design
Of Harmony and Stinginess: Applicative, Monad, and iterative library designOf Harmony and Stinginess: Applicative, Monad, and iterative library design
Of Harmony and Stinginess: Applicative, Monad, and iterative library design
 
Oojs 1.1
Oojs 1.1Oojs 1.1
Oojs 1.1
 
обзор Python
обзор Pythonобзор Python
обзор Python
 
掀起 Swift 的面紗
掀起 Swift 的面紗掀起 Swift 的面紗
掀起 Swift 的面紗
 
Writing Redis in Python with asyncio
Writing Redis in Python with asyncioWriting Redis in Python with asyncio
Writing Redis in Python with asyncio
 
Monads in Swift
Monads in SwiftMonads in Swift
Monads in Swift
 
Hierarchical free monads and software design in fp
Hierarchical free monads and software design in fpHierarchical free monads and software design in fp
Hierarchical free monads and software design in fp
 
DjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New RelicDjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New Relic
 
Djangocon11: Monkeying around at New Relic
Djangocon11: Monkeying around at New RelicDjangocon11: Monkeying around at New Relic
Djangocon11: Monkeying around at New Relic
 
Dnipro conf
Dnipro confDnipro conf
Dnipro conf
 
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
 
10. haskell Modules
10. haskell Modules10. haskell Modules
10. haskell Modules
 
Notes5
Notes5Notes5
Notes5
 
Gevent what's the point
Gevent what's the pointGevent what's the point
Gevent what's the point
 
10 reasons to adopt Python 3
10 reasons to adopt Python 310 reasons to adopt Python 3
10 reasons to adopt Python 3
 

Recently uploaded

Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsSnow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsHyundai Motor Group
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxnull - The Open Security Community
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 

Recently uploaded (20)

Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsSnow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 

Zope component architechture

  • 1. Zope Component Architecture There should be a silver bullet! Let's try to look for it with ZCA at least :) Anatoly Bubenkov @bubenkoff Paylogic Groningen Office 19.08.2013
  • 2. I you’ve heard something bad about zope... Then probably you don’t know what it is :) So i’ll tell you: ZOPE stands for The Object Publising Environment, so TOPE, but T -> Z to be polite. Name zope itself is a fish, Ballerus ballerus, also known as zope or blue bream, is a fish native to Eurasia. Some people say that python became popular in web development because of zope :)
  • 3. So what is zope? Object-oriented web application server and framework two main versions alive and actively developed: zope2 - mainly known because Plone CMF is based on it zope3, then BlueBream, then part of BlueBream became Zope Toolkit (ZTK). Many things from zope3 were backported to zope2, but zope3 is initially a full rewrite of zope2 using Component Architecture. And probably you’ve heard most of bad things about zope2.
  • 4. Component based architecture Basically the idea: ● objects(components) interact only through interfaces. ● single interface - various implementations possible.
  • 5. But interaction only through interfaces can be tricky... class ISize(Interface): “””Object size.””” size = Interface.Attribute(‘size’) --------------------component--------------------------- class IDocument(Interface): “””Text document.””” text = Interface.Attribute(‘text’) --------------------component--------------------------- class IImage(Interface): “””Image.””” image = Interface.Attribute(‘image’) --------------------component--------------------------- To get size from objects of various types, we need to implement ISize, but if we want to keep components separate, we can’t do it.
  • 6. So here comes an Adapter paradigm Adding adaptors, leads by-interface communication much more elegant, because you can control the interaction between objects through them without direct modification. IDocument -> ISize adaptor ISize IDocument IImage IImage -> ISize adaptor
  • 7. What do we have in python? ● PEP 246 (adaptation) and PEP 245 (interfaces) - killed by Guido in favor of __notimplemented__ ● zope.interface ● PyProtocols (not active since 2003) ● PEAK-Rules (allows you to HACK everything, so not a direct alternative, also seems not active already)
  • 8. zope.interface, here is the implementation The key package of: ● zope ● twisted ● pyramid even Shipped out of the box with OSX :) Pythonic (with C optimizations) implementation of component architechture. ● python3 ready ● pypy compliant
  • 9. zope.interface: 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""" 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' Interfaces can inherit from each other just like normal python classes.
  • 10. zope.interface: Interface implementation The most common way to declare interfaces is using the implements function in a class statement: >>> class Foo(object): ... 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 We can ask if interface is implemented by class: >>> IFoo.implementedBy(Foo) True Interface will be Provided by object, if it’s class implements it: >>> foo = Foo() >>> IFoo.providedBy(foo) True And of course interface is not provided by a class implementing it >>> IFoo.providedBy(Foo) False But it’s also possible to dynamically provide interface for an object via zope.interface.directlyProvides
  • 11. zope.interface: Invariants Invariants are validation expressions, where input is only depends on interface attributes. >>> 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(2,1)) Traceback (most recent call last): ... RangeError: Range(2, 1)
  • 12. zope.interface: Adapters 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
  • 13. Finding out what, if anything, is registered We can ask if there is an adapter registered for a collection of interfaces. This is different than lookup, because it looks for an exact match: >>> print registry.registered([IR1], IP1) 11 >>> print registry.registered([IR1], IP2) 12 >>> print registry.registered([IR1], IP2, 'bob') Bob's 12 >>> print registry.registered([IR2], IP1) 21 >>> print registry.registered([IR2], IP2) None
  • 14. 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
  • 15. 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
  • 16. 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() >>> assert 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() >>> assert adapters == [(u'', '1q22'), (u'bob', '1q2 for bob')]
  • 17. zope.interface: 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. You can have multiple subscribers for the same specification: >>> registry.subscribe([IR1], IP2, 'sub12 2') >>> registry.subscriptions([IR1], IP2) ['sub12 1', 'sub12 2'] If subscribers are registered for the same required interfaces, they are returned in the order of definition. You can register subscribers for all specifications using None: >>> registry.subscribe([None], IP1, 'sub_1') >>> registry.subscriptions([IR2], IP1) ['sub_1', 'sub12 1', 'sub12 2']
  • 18. zope.interface: 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
  • 19. zope.interface: 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
  • 20. Where it can be used? Basically in every ‘big and complex’ project. Providing a clear communication protocol for pieces of your big picture. Adaptors are great when you need a representation, for example a web-based view of an object. Handlers provide efficient event model. Interfaces give you contracts.
  • 21. ..And why? ● Having system of many independent components interacting via robust protocol is much better than monolithic approach when everyone knows everyone ● No need to invent the wheel (having api.py in each of your package) ● Relying on python imports potentially causes problems with circular dependencies, with zope.interface you only need interfaces (can be separate) for communication.
  • 22. Thanks! Questions? Reference: ● http://docs.zope.org/zope.interface/ ● http://docs.zope.org/zope.component/ ● http://www.muthukadan.net/docs/zca.html ● http://en.wikipedia.org/wiki/Zope ● http://en.wikipedia. org/wiki/Design_by_contract ● http://www.artima.com/weblogs/viewpost. jsp?thread=155123