[z3-checkins] r5282 - in z3/Five/trunk: . doc
faassen at codespeak.net
faassen at codespeak.net
Fri Jun 25 12:51:48 MEST 2004
Author: faassen
Date: Fri Jun 25 12:51:48 2004
New Revision: 5282
Added:
z3/Five/trunk/doc/manual.txt
Modified:
z3/Five/trunk/README.txt
Log:
Move manual style content out of README.txt into manual, and extend
manual.txt.
Modified: z3/Five/trunk/README.txt
==============================================================================
--- z3/Five/trunk/README.txt (original)
+++ z3/Five/trunk/README.txt Fri Jun 25 12:51:48 2004
@@ -12,254 +12,36 @@
THE LAW OF FIVES IS NEVER WRONG." -- Principia Discordia
-How to install Five
--------------------
+What is Five?
+-------------
-See ``INSTALL.txt``.
+The goal of five is to allow Zope 2 developers to use Zope 3
+technology right now, inside of Zope 2. This allows a gradual
+evolution of Zope 2 code to Zope 3.
-How to use Five
----------------
+Five already makes the following Zope 3 technologies available in Zope
+2:
-Five is only useful on the Python (Product) level, not from within the
-Zope Management Interface.
+* Zope 3 interfaces
-Adapters
---------
+* ZCML (Zope Configuration Markup Language)
-The immediate thing that Five brings to do the table are
-adapters. This section goes through some demo code to explain how
-everything is tied together. ``demo/FiveDemo`` is a demo Product you
-can install and examine that has all the presented here together.
-
-Zope 3 adapters depend on Zope 3 interfaces. To create a Zope 3
-interface you need to subclass it from
-``zope.interface.Interface``. Here is an example::
-
- from zope.interface import Interface
-
- class IMyInterface(Interface):
- """This is a Zope 3 interface.
- """
- def someMethod():
- """This method does amazing stuff.
- """
-
-Now to make some class declare that it implements this interface, you
-need to use the ``implements()`` function in the class::
-
- from zope.interface import implements
- from interfaces import IMyInterface
-
- class MyClass:
- implements(IMyInterface)
-
- def someMethod(self):
- return "I am alive! Alive!"
-
-For an explanation of the relation of Zope 3 interfaces to Zope 2
-interfaces, see below.
-
-Now let's set up the interface that we are adapting to::
-
- class INewInterface(Interface):
- """The interface we adapt to.
- """
-
- def anotherMethod():
- """This method does more stuff.
- """
-
-Next we'll work on the class that implements the adapter. The
-requirement to make a class that is an adapter is very simple; you
-only need to take a context object as the constructor. The context
-object is the object being adapted. An example::
-
- from zope.interface import implements
- from interfaces import INewInterface
-
- class MyAdapter:
- implements(INewInterface)
-
- def __init__(self, context):
- self.context = context
-
- def anotherMethod(self):
- return "We have adapted: %s" % self.context.someMethod()
-
-Next, we hook it all up using zcml. If the classes are in a module
-called ``classes.py`` and the interfaces in a module called
-``interfaces.py``, we can declare ``MyAdapter`` to be an adapter for
-``IMyInterface`` to ``INewInterface`` like this (in a file called
-``configure.zcml``)::
-
- <configure xmlns="http://namespaces.zope.org/zope">
-
- <adapter
- for=".interfaces.IMyInterface"
- provides=".interfaces.INewInterface"
- factory=".classes.MyAdapter" />
-
- </configure>
-
-The next step is to read ``configure.zcml`` so Zope can find these
-declarations. Do this by placing the following in the ``__init__.py``
-of your Zope product::
-
- from Products.Five import zcml
- import Products
-
- def initialize(context):
- zcml.process('configure.zcml', package=Products.FiveDemo)
-
-Any class that implements ``INewInterface`` can now be adapted to
-``INewInterface``, like this::
-
- from zope.component import getAdapter
- from classes import MyClass
- from interfaces import INewInterface
-
- object = MyClass()
- adapted = getAdapter(object, INewInterface)
- print adapted.anotherMethod()
+* Adapters
-A shortcut for ``getAdapter()`` is to call the interface directly,
-like this::
+* Zope 3 views, even for standard Zope objects
- adapted = INewInterface(object)
+* layers & skins
-Views in Five
--------------
+* Zope 3 page template engine
+
+* Zope 2 security declarations in ZCML instead of in Python code.
+
+How to install Five
+-------------------
+
+See ``INSTALL.txt``.
+
+How to use Five
+---------------
-This section will give a brief introduction on how to use the five
-view system. ``demo/FiveViewsDemo`` is a demo Product you can install
-and examine that has all the presented here tied together, please
-consult it for more details. ``tests/products/FiveTest`` actually
-contains a more detailed set of test views, trying a number of
-features. Finally, read up on the way Zope 3 does it. While Five is a
-subset of Zope 3 functionality and has been adapted to work with Zope
-2, much of Zope 3's documentation still works.
-
-Five enables you to create views for your own objects, or even built-in
-Zope objects, as long as two things are the case:
-
-* The object provides an Zope 3 interface, typically through its class.
-
-* The object (typically its class) is made viewable.
-
-Typically you give your classes an interface using the ``implements``
-directive in the class body::
-
- class MyClass:
- implements(ISomeInterface)
-
-For existing objects that you cannot modify this is not
-possible. Instead, we provide a ZCML directive to accomplish this. As
-an example, to make Zope's ``Folder`` (and all its subclasses)
-implement ``IFolder`` (an interface you defined), you can do the
-following in ZCML::
-
- <five:implements class="OFS.Folder.Folder"
- interface=".interfaces.IFolder" />
-
-``five`` in this case refers to the XML namespace for Five,
-``http://namespace.zope.org/five``.
-
-To make an object viewable through Five your object needs to mix in
-``Viewable``, which can be imported from Products.Five.api. For
-instance::
-
- from Products.Five.api import Viewable
-
- class MyClass(OFS.SimpleItem.Item, Viewable):
- implements(ISomeInterface)
-
-For existing Zope objects, this is not easily possible. We've provided
-another ZCML directive however to take care of that. To continue our
-example, to make Zope's ``Folder`` viewable through Five, you need to
-declare this in ZCML as well:
-
- <five:viewable class="OFS.Folder.Folder"/>
-
-This makes Folder look up Zope 3 views first, and then if they cannot be
-found, fall back on the regular Zope 2 views. This allows the ZMI to work
-still, but new views can be added on the fly.
-
-Note that at the point of writing it is only possible to make an object
-viewable through ZCML if this object does not already provide its own
-``__bobo_traverse__`` method.
-
-Views in Five are simple classes. The only requirements for a Five
-view class are:
-
- * They need an ``__init__()`` that take a context and a request
- attribute. Typically this comes from a base class, such as
- ``FiveView``.
-
- * They need to be initialized with the Zope 2 security system, as
- otherwise you cannot use the view.
-
- * This also means they need to be part of the Zope 2 acquisition
- system, as this is a requirement for Zope 2 security to
- function. The ``BrowserView`` base class, available from
- ``Products.Five.api``, already inherits from
- ``Acquisition.Explicit`` to make this be the case. Acquisition is
- explicit so no attributes can be acquired by accident.
-
-An example of a simple view::
-
- from Products.Five.api import BrowserView
-
- class SimpleFolderView(BrowserView):
- security = ClassSecurityInfo()
-
- security.declarePublic('eagle')
- def eagle(self):
- """Test
- """
- return "The eagle has landed: %s" % self.context.objectIds()
-
- InitializeClass(SimpleFolderView)
-
-Note that it is not a good idea to give a view class its own
-``index_html``, as this confuses Five's view lookup machinery.
-
-As you can see, the class is initialized with the Zope 2 security
-system. This view uses methods in Python, but you can also use other
-Zope 2 mechanisms such as ``PageTemplateFile``.
-
-Finally, we need to hook up the pages through ZCML::
-
- <browser:page
- for=".interfaces.IFolder"
- class=".browser.SimpleFolderView"
- attribute="eagle"
- name="eagle.txt"
- permission="zope.ViewManagementScreens"
- />
-
-``browser`` in this refers to the XML namespace of Zope 3 for browser
-related things; it's
-``http://namespace.zope.org/browser``. ``permission`` declares the
-Zope 2 permission needs in order to access this view. The file
-``permissions.zcml`` in Five contains a mapping of Zope 2 permissions
-to their Zope 3 names.
-
-Interfaces in Zope 2 versus Zope 3
-----------------------------------
-
-Zope 2 has used the ``__implements__`` class attribute for interface
-declarations. Zope 2 cannot detect Zope 3 interfaces and the
-Zope 3 machinery cannot detect Zope 2 interfaces. This is a good
-thing, as Zope 2 has no way to deal with Zope 3 interfaces, and Zope 3
-cannot comprehend Zope 2 interfaces. It also means you can safely
-these interface declarations in a class. It's a rare case where you
-need this though; you're better off just switching to ``implements()``
-for your application if you are using Five.
-
-Switching from Zope 2 interfaces to Zope 3 interfaces is easy -- just
-make your interfaces inherit from ``zope.interface.Interface`` instead
-of ``Interface.Interface`` (or ``Interface.Base``). This should get
-you going and your application may very well still work. Later on, you
-will also have to change calls to ``isImplementedBy`` and such in your
-application to ``providedBy``, as ``isImplementedBy`` has been
-deprecated (you'll see the DeprecationWarnings in your log).
+Please see ``doc/manual.txt``.
Added: z3/Five/trunk/doc/manual.txt
==============================================================================
--- (empty file)
+++ z3/Five/trunk/doc/manual.txt Fri Jun 25 12:51:48 2004
@@ -0,0 +1,342 @@
+Introduction
+------------
+
+Five's goal is to let you, the Zope 2 developer, use Zope 3 code in
+Zope 2. Our aim is to make as much of Zope 3 code work in Zope 2 as
+possible, while integrating it with Zope 2.
+
+Five can be used inside your current Zope 2 project. The benefits are:
+
+* availability of Zope 3 technologies in Zope 2 like the component
+ architecture and declarative configuration.
+
+* you can gradually evolve your Zope 2 project so it is better
+ positioned for the migration to Zope 3.
+
+* you start learning about Zope 3 right now, preparing yourself better
+ for the future. Since Zope 3 is open to contributions, you could
+ even influence your future for the better.
+
+Five can also be used to develop new Zope 2 products, though depending
+on your deployment requirements it might in that case it might make
+more sense to develop for Zope 3 directly.
+
+Five is only useful on the Python (Product) level in Zope 2, not from
+within the Zope Management Interface. Five makes no attempt to provide
+a user interface, but it aimed squarely at the Python developer.
+
+Zope 3 interfaces
+-----------------
+
+Interfaces?
+===========
+
+An interface is simply a description of what an object provides to the
+world, i.e. its public attribute and methods. It looks very much like
+a class, but contains no implementation::
+
+ from zope.interface import Interface
+
+ # by convention, all interfaces are prefixed with ``I``
+ class IElephant(Interface):
+ """An elephant is a big object that barely fits in the cupboard.
+ """
+
+ def getAngerLevel():
+ """Anger level, maximum of 100.
+
+ The longer the elephant has been in the cupboard, the angrier.
+ """
+
+ def isInCupboard():
+ """Returns true if the elephant is indeed in cupboard.
+ """
+
+ def trunkSmash(target):
+ """Smash the target with trunk.
+
+ The anger level determines the force of the hit.
+ """
+
+ def trample(target):
+ """Trample the target.
+
+ The anger level determines the rate of flattening of the target.
+ """
+
+A concrete class somewhere can now claim that it implements the
+interface (i.e. its instance will provide the interface)::
+
+ class PinkElephant:
+ # this says all instances of this class provide IElephant
+ implements(IElephant)
+
+ def getAngerLevel(self):
+ return 0 # this elephant is peaceful
+
+ def isInCupboard(self):
+ return False # it's never in a cupboard but can be found in bottles
+
+ def trunkSmash(self, target):
+ target.tickle()
+
+ def trample(self, target):
+ target.patOnHead()
+
+Interfaces themselves are good for a number of reasons:
+
+ * They provide API documentation.
+
+ * They help you make explicit the design of your application, hopefully
+ improving it.
+
+ * If an object declares an interface, that object is considered to
+ be a *component*. This means you can use Zope 3's component
+ architecture with these objects.
+
+Interfaces in Zope 2 versus Zope 3
+==================================
+
+You may be familiar with Zope 2's way of declaring interfaces. Zope 2
+has used the ``__implements__`` class attribute for interface
+declarations. Zope 2 cannot detect Zope 3 interfaces and the Zope 3
+machinery cannot detect Zope 2 interfaces. This is a good thing, as
+Zope 2 has no way to deal with Zope 3 interfaces, and Zope 3 cannot
+comprehend Zope 2 interfaces. This means you can safely make a class
+declare both a Zope 2 and Zope 3 interface independently from each
+other. It's a rare case where you need this though; you're usually
+better off just switching to ``implements()`` for your application if
+you are using Five.
+
+Switching from Zope 2 interfaces to Zope 3 interfaces is easy -- just
+make your interfaces inherit from ``zope.interface.Interface`` instead
+of ``Interface.Interface`` (or ``Interface.Base``). Next, change all
+``_implements__`` to ``implements()``.
+
+This should get you going and your application may very well still
+work. Later on, you will also have to change calls to
+``isImplementedBy`` and such in your application to ``providedBy``, as
+``isImplementedBy`` has been deprecated (you'll see the
+DeprecationWarnings in your Zope log).
+
+Adapters
+--------
+
+The immediate thing that Five brings to do the table are
+adapters. This section goes through some demo code to explain how
+everything is tied together. ``demo/FiveDemo`` is a demo Product you
+can install and examine that has all the presented here together.
+
+Zope 3 adapters depend on Zope 3 interfaces. To create a Zope 3
+interface you need to subclass it from
+``zope.interface.Interface``. Here is an example::
+
+ from zope.interface import Interface
+
+ class IMyInterface(Interface):
+ """This is a Zope 3 interface.
+ """
+ def someMethod():
+ """This method does amazing stuff.
+ """
+
+Now to make some class declare that it implements this interface, you
+need to use the ``implements()`` function in the class::
+
+ from zope.interface import implements
+ from interfaces import IMyInterface
+
+ class MyClass:
+ implements(IMyInterface)
+
+ def someMethod(self):
+ return "I am alive! Alive!"
+
+For an explanation of the relation of Zope 3 interfaces to Zope 2
+interfaces, see below.
+
+Now let's set up the interface that we are adapting to::
+
+ class INewInterface(Interface):
+ """The interface we adapt to.
+ """
+
+ def anotherMethod():
+ """This method does more stuff.
+ """
+
+Next we'll work on the class that implements the adapter. The
+requirement to make a class that is an adapter is very simple; you
+only need to take a context object as the constructor. The context
+object is the object being adapted. An example::
+
+ from zope.interface import implements
+ from interfaces import INewInterface
+
+ class MyAdapter:
+ implements(INewInterface)
+
+ def __init__(self, context):
+ self.context = context
+
+ def anotherMethod(self):
+ return "We have adapted: %s" % self.context.someMethod()
+
+Next, we hook it all up using zcml. If the classes are in a module
+called ``classes.py`` and the interfaces in a module called
+``interfaces.py``, we can declare ``MyAdapter`` to be an adapter for
+``IMyInterface`` to ``INewInterface`` like this (in a file called
+``configure.zcml``)::
+
+ <configure xmlns="http://namespaces.zope.org/zope">
+
+ <adapter
+ for=".interfaces.IMyInterface"
+ provides=".interfaces.INewInterface"
+ factory=".classes.MyAdapter" />
+
+ </configure>
+
+The next step is to read ``configure.zcml`` so Zope can find these
+declarations. Do this by placing the following in the ``__init__.py``
+of your Zope product::
+
+ from Products.Five import zcml
+ import Products
+
+ def initialize(context):
+ zcml.process('configure.zcml', package=Products.FiveDemo)
+
+Any class that implements ``INewInterface`` can now be adapted to
+``INewInterface``, like this::
+
+ from zope.component import getAdapter
+ from classes import MyClass
+ from interfaces import INewInterface
+
+ object = MyClass()
+ adapted = getAdapter(object, INewInterface)
+ print adapted.anotherMethod()
+
+A shortcut for ``getAdapter()`` is to call the interface directly,
+like this::
+
+ adapted = INewInterface(object)
+
+Views in Five
+-------------
+
+This section will give a brief introduction on how to use the five
+view system. ``demo/FiveViewsDemo`` is a demo Product you can install
+and examine that has all the presented here tied together, please
+consult it for more details. ``tests/products/FiveTest`` actually
+contains a more detailed set of test views, trying a number of
+features. Finally, read up on the way Zope 3 does it. While Five is a
+subset of Zope 3 functionality and has been adapted to work with Zope
+2, much of Zope 3's documentation still works.
+
+Five enables you to create views for your own objects, or even built-in
+Zope objects, as long as two things are the case:
+
+* The object provides an Zope 3 interface, typically through its class.
+
+* The object (typically its class) is made viewable.
+
+Typically you give your classes an interface using the ``implements``
+directive in the class body::
+
+ class MyClass:
+ implements(ISomeInterface)
+
+For existing objects that you cannot modify this is not
+possible. Instead, we provide a ZCML directive to accomplish this. As
+an example, to make Zope's ``Folder`` (and all its subclasses)
+implement ``IFolder`` (an interface you defined), you can do the
+following in ZCML::
+
+ <five:implements class="OFS.Folder.Folder"
+ interface=".interfaces.IFolder" />
+
+``five`` in this case refers to the XML namespace for Five,
+``http://namespace.zope.org/five``.
+
+To make an object viewable through Five your object needs to mix in
+``Viewable``, which can be imported from Products.Five.api. For
+instance::
+
+ from Products.Five.api import Viewable
+
+ class MyClass(OFS.SimpleItem.Item, Viewable):
+ implements(ISomeInterface)
+
+For existing Zope objects, this is not easily possible. We've provided
+another ZCML directive however to take care of that. To continue our
+example, to make Zope's ``Folder`` viewable through Five, you need to
+declare this in ZCML as well:
+
+ <five:viewable class="OFS.Folder.Folder"/>
+
+This makes Folder look up Zope 3 views first, and then if they cannot be
+found, fall back on the regular Zope 2 views. This allows the ZMI to work
+still, but new views can be added on the fly.
+
+Note that at the point of writing it is only possible to make an object
+viewable through ZCML if this object does not already provide its own
+``__bobo_traverse__`` method.
+
+Views in Five are simple classes. The only requirements for a Five
+view class are:
+
+ * They need an ``__init__()`` that take a context and a request
+ attribute. Typically this comes from a base class, such as
+ ``FiveView``.
+
+ * They need to be initialized with the Zope 2 security system, as
+ otherwise you cannot use the view.
+
+ * This also means they need to be part of the Zope 2 acquisition
+ system, as this is a requirement for Zope 2 security to
+ function. The ``BrowserView`` base class, available from
+ ``Products.Five.api``, already inherits from
+ ``Acquisition.Explicit`` to make this be the case. Acquisition is
+ explicit so no attributes can be acquired by accident.
+
+An example of a simple view::
+
+ from Products.Five.api import BrowserView
+
+ class SimpleFolderView(BrowserView):
+ security = ClassSecurityInfo()
+
+ security.declarePublic('eagle')
+ def eagle(self):
+ """Test
+ """
+ return "The eagle has landed: %s" % self.context.objectIds()
+
+ InitializeClass(SimpleFolderView)
+
+Note that it is not a good idea to give a view class its own
+``index_html``, as this confuses Five's view lookup machinery.
+
+As you can see, the class is initialized with the Zope 2 security
+system. This view uses methods in Python, but you can also use other
+Zope 2 mechanisms such as ``PageTemplateFile``.
+
+Finally, we need to hook up the pages through ZCML::
+
+ <browser:page
+ for=".interfaces.IFolder"
+ class=".browser.SimpleFolderView"
+ attribute="eagle"
+ name="eagle.txt"
+ permission="zope.ViewManagementScreens"
+ />
+
+``browser`` in this refers to the XML namespace of Zope 3 for browser
+related things; it's
+``http://namespace.zope.org/browser``. ``permission`` declares the
+Zope 2 permission needs in order to access this view. The file
+``permissions.zcml`` in Five contains a mapping of Zope 2 permissions
+to their Zope 3 names.
+
More information about the z3-checkins
mailing list