[Checkins] SVN: zope2docs/trunk/zdgbook/source/Products.rst Bit cleanup again

Baiju M baiju.m.mail at gmail.com
Thu Oct 8 23:06:54 EDT 2009


Log message for revision 104955:
  Bit cleanup again
  

Changed:
  U   zope2docs/trunk/zdgbook/source/Products.rst

-=-
Modified: zope2docs/trunk/zdgbook/source/Products.rst
===================================================================
--- zope2docs/trunk/zdgbook/source/Products.rst	2009-10-08 21:09:19 UTC (rev 104954)
+++ zope2docs/trunk/zdgbook/source/Products.rst	2009-10-09 03:06:54 UTC (rev 104955)
@@ -52,22 +52,22 @@
   from zope.interface import Interface
 
   class IPoll(Interface):
-      "A multiple choice poll"
+      """A multiple choice poll"""
 
       def castVote(index):
-          "Votes for a choice"
+          """Votes for a choice"""
 
       def getTotalVotes():
-          "Returns total number of votes cast"
+          """Returns total number of votes cast"""
 
       def getVotesFor(index):
-          "Returns number of votes cast for a given response"
+          """Returns number of votes cast for a given response"""
 
       def getResponses():
-          "Returns the sequence of responses"
+          """Returns the sequence of responses"""
 
       def getQuestion():
-          "Returns the question
+          """Returns the question"""
 
 How you name your interfaces is entirely up to you.  Here we've
 decided to use prefix "I" in the name of the interface.
@@ -78,15 +78,14 @@
 After you have defined an interface for your product, the next step
 is to create a prototype in Python that implements your interface.
 
-Here is a prototype of a 'PollImplemtation' class that implements the
+Here is a prototype of a ``PollImplemtation`` class that implements the
 interface you just examined (see `PollImplementation.py
 <examples/PollImplementation.py>`_)::
 
   from poll import Poll
 
   class PollImplementation:
-      """
-      A multiple choice poll, implements the Poll interface.
+      """A multiple choice poll, implements the Poll interface.
 
       The poll has a question and a sequence of responses. Votes
       are stored in a dictionary which maps response indexes to a
@@ -103,29 +102,29 @@
               self._votes[i] = 0
 
       def castVote(self, index):
-          "Votes for a choice"
+          """Votes for a choice"""
           self._votes[index] = self._votes[index] + 1
 
       def getTotalVotes(self):
-          "Returns total number of votes cast"
+          """Returns total number of votes cast"""
           total = 0
           for v in self._votes.values():
               total = total + v
           return total
 
       def getVotesFor(self, index):
-          "Returns number of votes cast for a given response"
+          """Returns number of votes cast for a given response"""
           return self._votes[index]
 
       def getResponses(self):
-          "Returns the sequence of responses"
+          """Returns the sequence of responses"""
           return tuple(self._responses)
 
       def getQuestion(self):
-          "Returns the question"
+          """Returns the question"""
           return self._question
 
-You can use this class interactively and test it. Here's an example
+You can use this class interactively and test it.  Here's an example
 of interactive testing::
 
   >>> from PollImplementation import PollImplementation
@@ -150,25 +149,25 @@
   self._votes[index] = self._votes[index] + 1
   KeyError: 4
 
-Interactive testing is one of Python's great features. It lets you
+Interactive testing is one of Python's great features.  It lets you
 experiment with your code in a simple but powerful way.
 
 At this point you can do a fair amount of work, testing and refining
-your interfaces and classes which implement them. See Chapter 7 for
+your interfaces and classes which implement them.  See Chapter 9 for
 more information on testing.
 
 So far you have learned how to create Python classes that are
-documented with interfaces, and verified with testing. Next you'll
-examine the Zope product architecture. Then you'll learn how to fit
+documented with interfaces, and verified with testing.  Next you'll
+examine the Zope product architecture.  Then you'll learn how to fit
 your well crafted Python classes into the product framework.
 
 Building Product Classes
 ------------------------
 
-To turn a component into a product you must fulfill many
-contracts. For the most part these contracts are not yet defined in
-terms of interfaces. Instead you must subclass from base classes that
-implement the contracts. This makes building products confusing, and
+To turn a component into a product you must fulfill many contracts.
+For the most part these contracts are not yet defined in terms of
+interfaces.  Instead you must subclass from base classes that
+implement the contracts.  This makes building products confusing, and
 this is an area that we are actively working on improving.
 
 Base Classes
@@ -191,20 +190,20 @@
 take precedence over others.  Most Zope classes do not define similar
 names, so you usually don't need to worry about what order these
 classes are used in your product.  Let's take a look at each of these
-base classes:
+base classes.
 
 
 Acquisition.Implicit
 ~~~~~~~~~~~~~~~~~~~~
 
-This is the normal acquisition base class. See the *API Reference*
-for the full details on this class. Many Zope services such as object
-publishing and security use acquisition, so inheriting from this
-class is required for products. Actually, you can choose to inherit
-from 'Acquisition.Explicit' if you prefer, however, it will prevent
-folks from dynamically binding Python Scripts and DTML Methods to
-instances of your class. In general you should subclass from
-'Acquisition.Implicit' unless you have a good reason not to.
+This is the normal acquisition base class.  See the *API Reference*
+for the full details on this class.  Many Zope services such as
+object publishing and security use acquisition, so inheriting from
+this class is required for products.  Actually, you can choose to
+inherit from ``Acquisition.Explicit`` if you prefer, however, it will
+prevent folks from dynamically binding Python Scripts and DTML
+Methods to instances of your class.  In general you should subclass
+from ``Acquisition.Implicit`` unless you have a good reason not to.
 
   XXX: is this true?  I thought that any ExtensionClass.Base can be
   acquired.  The Implicit and Explicit just control how the class can
@@ -213,22 +212,22 @@
 Globals.Persistent
 ~~~~~~~~~~~~~~~~~~
 
-This base class makes instances of your product persistent. For more
+This base class makes instances of your product persistent.  For more
 information on persistence and this class see Chapter 4.
 
 In order to make your poll class persistent you'll need to make one
-change. Since '_votes' is a dictionary this means that it's a mutable
-non-persistent sub-object. You'll need to let the persistence
-machinery know when you change it::
+change.  Since ``_votes`` is a dictionary this means that it's a
+mutable non-persistent sub-object.  You'll need to let the
+persistence machinery know when you change it::
 
   def castVote(self, index):
-      "Votes for a choice"
+      """Votes for a choice"""
       self._votes[index] = self._votes[index] + 1
       self._p_changed = 1
 
-The last line of this method sets the '_p_changed' attribute to 1.
+The last line of this method sets the ``_p_changed`` attribute to 1.
 This tells the persistence machinery that this object has changed and
-should be marked as 'dirty', meaning that its new state should be
+should be marked as ``dirty``, meaning that its new state should be
 written to the database at the conclusion of the current transaction.
 A more detailed explanation is given in the Persistence chapter of
 this guide.
@@ -238,35 +237,37 @@
 ~~~~~~~~~~~~~~~~~~~
 
 This base class provides your product with the basics needed to work
-with the Zope management interface.  By inheriting from 'Item' your
+with the Zope management interface.  By inheriting from ``Item`` your
 product class gains a whole host of features: the ability to be cut
 and pasted, capability with management views, WebDAV support, basic
 FTP support, undo support, ownership support, and traversal controls.
 It also gives you some standard methods for management views and
-error display including 'manage_main()'.  You also get the 'getId()',
-'title_or_id()', 'title_and_id()' methods and the 'this()' DTML
-utility method. Finally this class gives your product basic
-*dtml-tree* tag support.  'Item' is really an
+error display including ``manage_main()``.  You also get the
+``getId()``, ``title_or_id()``, ``title_and_id()`` methods and the
+``this()`` DTML utility method.  Finally this class gives your
+product basic *dtml-tree* tag support.  ``Item`` is really an
 everything-but-the-kitchen-sink kind of base class.
 
-'Item' requires that your class and instances have some management
+``Item`` requires that your class and instances have some management
 interface related attributes.
 
-'meta_type' -- This attribute should be a short string which is the
-name of your product class as it appears in the product add list. For
-example the poll product class could have a 'meta_type' of 'Poll'.
+- ``meta_type`` -- This attribute should be a short string which is
+  the name of your product class as it appears in the product add
+  list.  For example, the poll product class could have a
+  ``meta_type`` with value as ``Poll``.
 
-'id' or '__name__' -- All 'Item' instances must have an 'id' string
-attribute which uniquely identifies the instance within it's
-container. As an alternative you may use '__name__' instead of 'id'.
+- ``id`` or ``__name__`` -- All ``Item`` instances must have an
+  ``id`` string attribute which uniquely identifies the instance
+  within it's container.  As an alternative you may use ``__name__``
+  instead of ``id``.
 
-'title' -- All 'Item' instances must have a 'title' string
-attribute. A title may be an empty string if your instance does not
-have a title.
+- ``title`` -- All ``Item`` instances must have a ``title`` string
+  attribute.  A title may be an empty string if your instance does
+  not have a title.
 
-In order to make your poll class work correctly as an 'Item' you'll
-need to make a few changes. You must add a 'meta_type' class
-attribute, and you may wish to add an 'id' parameter to the
+In order to make your poll class work correctly as an ``Item`` you'll
+need to make a few changes.  You must add a ``meta_type`` class
+attribute, and you may wish to add an ``id`` parameter to the
 constructor::
 
   class PollProduct(..., Item):
@@ -283,73 +284,74 @@
               self._votes[i] = 0
 
 
-Finally, you should probably place 'Item' last in your list of base
-classes. The reason for this is that 'Item' provides defaults that
-other classes such as 'ObjectManager' and 'PropertyManager'
-override. By placing other base classes before 'Item' you allow them
-to override methods in 'Item'.
+Finally, you should probably place ``Item`` last in your list of base
+classes.  The reason for this is that ``Item`` provides defaults that
+other classes such as ``ObjectManager`` and ``PropertyManager``
+override.  By placing other base classes before ``Item`` you allow
+them to override methods in ``Item``.
 
 AccessControl.Role.RoleManager
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 This class provides your product with the ability to have its
-security policies controlled through the web. See Chapter 6 for more
+security policies controlled through the web.  See Chapter 6 for more
 information on security policies and this class.
 
 OFS.ObjectManager
 ~~~~~~~~~~~~~~~~~
 
 This base class gives your product the ability to contain other
-'Item' instances. In other words, it makes your product class like a
-Zope folder. This base class is optional. See the *API Reference* for
-more details. This base class gives you facilities for adding Zope
-objects, importing and exporting Zope objects, WebDAV, and FTP. It
-also gives you the 'objectIds', 'objectValues', and 'objectItems'
-methods.
+``Item`` instances.  In other words, it makes your product class like
+a Zope folder.  This base class is optional. See the *API Reference*
+for more details.  This base class gives you facilities for adding
+Zope objects, importing and exporting Zope objects, WebDAV, and FTP.
+It also gives you the ``objectIds``, ``objectValues``, and
+``objectItems`` methods.
 
-'ObjectManager' makes few requirements on classes that subclass
-it. You can choose to override some of its methods but there is
-little that you must do.
+``ObjectManager`` makes few requirements on classes that subclass it.
+You can choose to override some of its methods but there is little
+that you must do.
 
 If you wish to control which types of objects can be contained by
-instances of your product you can set the 'meta_types' class
-attribute. This attribute should be a tuple of meta_types. This keeps
-other types of objects from being created in or pasted into instances
-of your product. The 'meta_types' attribute is mostly useful when you
-are creating specialized container products.
+instances of your product you can set the ``meta_types`` class
+attribute.  This attribute should be a tuple of meta_types.  This
+keeps other types of objects from being created in or pasted into
+instances of your product.  The ``meta_types`` attribute is mostly
+useful when you are creating specialized container products.
 
 OFS.PropertyManager
 ~~~~~~~~~~~~~~~~~~~
 
 This base class provides your product with the ability to have
-user-managed instance attributes. See the *API Reference* for more
+user-managed instance attributes.  See the *API Reference* for more
 details.  This base class is optional.
 
 Your class may specify that it has one or more predefined properties,
-by specifying a '_properties' class attribute. For example::
+by specifying a '_properties' class attribute.  For example::
 
   _properties=({'id':'title', 'type': 'string', 'mode': 'w'},
                {'id':'color', 'type': 'string', 'mode': 'w'},
               )
 
-The '_properties' structure is a sequence of dictionaries, where each
-dictionary represents a predefined property. Note that if a
-predefined property is defined in the '_properties' structure, you
+The ``_properties`` structure is a sequence of dictionaries, where
+each dictionary represents a predefined property.  Note that if a
+predefined property is defined in the ``_properties`` structure, you
 must provide an attribute with that name in your class or instance
 that contains the default value of the predefined property.
 
-Each entry in the '_properties' structure must have at least an 'id'
-and a 'type' key. The 'id' key contains the name of the property, and
-the 'type' key contains a string representing the object's type.  The
-'type' string must be one of the values: 'float', 'int', 'long',
-'string', 'lines', 'text', 'date', 'tokens', 'selection', or
-'multiple section'. For more information on Zope properties see the
-*Zope Book*.
+Each entry in the ``_properties`` structure must have at least an
+``id`` and a ``type`` key.  The ``id`` key contains the name of the
+property, and the ``type`` key contains a string representing the
+object's type.  The ``type`` string must be one of the values:
+``float``, ``int``, ``long``, ``string``, ``lines``, ``text``,
+``date``, ``tokens``, ``selection``, or ``multiple section``.  For
+more information on Zope properties see the *Zope Book*.
 
-For 'selection' and 'multiple selection' properties, you must include
-an addition item in the property dictionary, 'select_variable' which
-provides the name of a property or method which returns a list of
-strings from which the selection(s) can be chosen. For example::
+For ``selection`` and ``multiple selection`` properties, you must
+include an addition item in the property dictionary,
+``select_variable`` which provides the name of a property or method
+which returns a list of strings from which the selection(s) can be
+chosen.  For example::
 
   _properties=({'id' : 'favorite_color',
                 'type' : 'selection',
@@ -357,25 +359,25 @@
                },
               )
 
-Each entry in the '_properties' structure may optionally provide a
-'mode' key, which specifies the mutability of the property. The
-'mode' string, if present, must be 'w', 'd', or 'wd'.
+Each entry in the ``_properties`` structure may optionally provide a
+``mode`` key, which specifies the mutability of the property. The
+``mode`` string, if present, must be ``w``, ``d``, or ``wd``.
 
-A 'w' present in the mode string indicates that the value of the
-property may be changed by the user. A 'd' indicates that the user
-can delete the property. An empty mode string indicates that the
+A ``w`` present in the mode string indicates that the value of the
+property may be changed by the user.  A ``d`` indicates that the user
+can delete the property.  An empty mode string indicates that the
 property and its value may be shown in property listings, but that it
 is read-only and may not be deleted.
 
-Entries in the '_properties' structure which do not have a 'mode'
-item are assumed to have the mode 'wd' (writable and deleteable).
+Entries in the ``_properties`` structure which do not have a ``mode``
+item are assumed to have the mode ``wd`` (writable and deleteable).
 
 Security Declarations
 ---------------------
 
 In addition to inheriting from a number of standard base classes, you
 must declare security information in order to turn your component
-into a product. See Chapter 6 for more information on security and
+into a product.  See Chapter 6 for more information on security and
 instructions for declaring security on your components.
 
 Here's an example of how to declare security on the poll class::
@@ -408,7 +410,7 @@
           ...
 
 For security declarations to be set up Zope requires that you
-initialize your product class. Here's how to initialize your poll
+initialize your product class.  Here's how to initialize your poll
 class::
 
   from Globals import InitializeClass
@@ -421,8 +423,8 @@
 Summary
 -------
 
-Congratulations, you've created a product class. Here it is in all
-its glory (see "PollProduct.py":examples/PollProduct.py)::
+Congratulations, you've created a product class.  Here it is in all
+its glory (see `examples/PollProduct.py <PollProduct.py>`_)::
 
   from Poll import Poll
   from AccessControl import ClassSecurityInfo
@@ -433,8 +435,7 @@
   from OFS.SimpleItem import Item
 
   class PollProduct(Implicit, Persistent, RoleManager, Item):
-      """
-      Poll product class, implements Poll interface.
+      """Poll product class, implements Poll interface.
 
       The poll has a question and a sequence of responses. Votes
       are stored in a dictionary which maps response indexes to a
@@ -486,14 +487,14 @@
 
   InitializeClass(Poll)
 
-Now it's time to test your product class in Zope. To do this you must
-register your product class with Zope.
+Now it's time to test your product class in Zope.  To do this you
+must register your product class with Zope.
 
 Registering Products
 ====================
 
 Products are Python packages that live in 'lib/python/Products'.
-Products are loaded into Zope when Zope starts up. This process is
+Products are loaded into Zope when Zope starts up.  This process is
 called *product initialization*.  During product initialization, each
 product is given a chance to register its capabilities with Zope.
 
@@ -501,9 +502,9 @@
 ----------------------
 
 When Zope starts up it imports each product and calls the product's
-'initialize' function passing it a registrar object. The 'initialize'
-function uses the registrar to tell Zope about its capabilities. Here
-is an example '__init__.py' file::
+'initialize' function passing it a registrar object.  The
+'initialize' function uses the registrar to tell Zope about its
+capabilities.  Here is an example '__init__.py' file::
 
   from PollProduct import PollProduct, addForm, addFunction
 
@@ -513,10 +514,10 @@
           constructors=(addForm, addFunction),
           )
 
-This function makes one call to the registrar object which registers
-a class as an addable object.  The registrar figures out the name to
-put in the product add list by looking at the 'meta_type' of the
-class.  Zope also deduces a permission based on the class's
+This function makes one call to the *registrar* object which
+registers a class as an addable object.  The *registrar* figures out
+the name to put in the product add list by looking at the 'meta_type'
+of the class.  Zope also deduces a permission based on the class's
 meta-type, in this case *Add Polls* (Zope automatically pluralizes
 "Poll" by adding an "s").  The 'constructors' argument is a tuple of
 objects consisting of two functions: an add form which is called when
@@ -530,7 +531,7 @@
 has the constructor permission.
 
 See the *API Reference* for more information on the
-'ProductRegistrar' interface.
+``ProductRegistrar`` interface.
 
 Factories and Constructors
 --------------------------
@@ -555,32 +556,30 @@
 relevant data.  Here's a very simple add form function for the poll
 class::
 
-        def addForm():
-            """
-            Returns an HTML form.
-            """
-            return """<html>
-            <head><title>Add Poll</title></head>
-            <body>
-            <form action="addFunction">
-            id <input type="type" name="id"><br>
-            question <input type="type" name="question"><br>
-            responses (one per line)
-            <textarea name="responses:lines"></textarea>
-            </form>
-            </body>
-            </html>"""
+  def addForm():
+      """Returns an HTML form."""
+      return """<html>
+      <head><title>Add Poll</title></head>
+      <body>
+      <form action="addFunction">
+      id <input type="type" name="id"><br>
+      question <input type="type" name="question"><br>
+      responses (one per line)
+      <textarea name="responses:lines"></textarea>
+      </form>
+      </body>
+      </html>"""
 
-Notice how the action of the form is 'addFunction'.  Also notice how
-the lines of the response are marshalled into a sequence.  See
+Notice how the action of the form is ``addFunction``.  Also notice
+how the lines of the response are marshalled into a sequence.  See
 Chapter 2 for more information about argument marshalling and object
 publishing.
 
-It's also important to include a HTML 'head' tag in the add
-form.  This is necessary so that Zope can set the base URL to make
-sure that the relative link to the 'addFunction' works correctly.
+It's also important to include a HTML ``head`` tag in the add form.
+This is necessary so that Zope can set the base URL to make sure that
+the relative link to the ``addFunction`` works correctly.
 
-The add function will be passed a 'FactoryDispatcher' as its first
+The add function will be passed a ``FactoryDispatcher`` as its first
 argument which proxies the location (usually a Folder) where your
 product was added.  The add function may also be passed any form
 variables which are present in your add form according to normal
@@ -596,19 +595,18 @@
 
 The dispatcher has three methods:
 
-'Destination' -- The 'ObjectManager' where your product was added.
+- ``Destination`` -- The ``ObjectManager`` where your product was added.
 
-'DestinationURL' -- The URL of the 'ObjectManager' where your product
-was added.
+- ``DestinationURL`` -- The URL of the ``ObjectManager`` where your
+  product was added.
 
-'manage_main' -- Redirects to a management view of the
-'ObjectManager' where your product was added.
+- ``manage_main`` -- Redirects to a management view of the
+  ``ObjectManager`` where your product was added.
 
-Notice how it calls the '_setObject()' method of the destination
-'ObjectManager' class to add the poll to the folder.  See the *API
-Reference* for more information on the 'ObjectManager' interface.
+Notice how it calls the ``_setObject()`` method of the destination
+``ObjectManager`` class to add the poll to the folder.  See the *API
+Reference* for more information on the ``ObjectManager`` interface.
 
-
 The add function should also check the validity of its input.  For
 example the add function should complain if the question or response
 arguments are not of the correct type.
@@ -625,19 +623,19 @@
 
 Now you're ready to register your product with Zope.  You need to add
 the add form and add method to the poll module.  Then you should
-create a 'Poll' directory in your 'lib/python/Products' directory and
-add the 'Poll.py', 'PollProduct.py', and '__init__.py' files.  Then
+create a `Poll` directory in your `lib/python/Products` directory and
+add the `Poll.py`, `PollProduct.py`, and `__init__.py` files.  Then
 restart Zope.
 
 Now login to Zope as a manager and visit the web management
-interface. You should see a 'Poll' product listed inside the
-*Products* folder in the *Control_Panel*. If Zope had trouble
-initializing your product you will see a traceback here. Fix your
-problems, if any and restart Zope. If you are tired of all this
+interface.  You should see a 'Poll' product listed inside the
+*Products* folder in the *Control_Panel*.  If Zope had trouble
+initializing your product you will see a traceback here.  Fix your
+problems, if any and restart Zope.  If you are tired of all this
 restarting, take a look at the *Refresh* facility covered in Chapter
 7.
 
-Now go to the root folder. Select *Poll* from the product add list.
+Now go to the root folder.  Select *Poll* from the product add list.
 Notice how you are taken to the add form.  Provide an id, a question,
 and a list of responses and click *Add*.  Notice how you get a black
 screen.  This is because your add method does not return anything.
@@ -649,69 +647,68 @@
 your poll instance.  Here's a Python Script to figure out voting
 percentages::
 
-        ## Script (Python) "getPercentFor"
-        ##parameters=index
-        ##
-        """Returns the percentage of the vote given a response index. Note,
-        this script should be bound a poll by acquisition context."""
-        poll = context
-        return float(poll.getVotesFor(index)) / poll.getTotalVotes()
+  ## Script (Python) "getPercentFor"
+  ##parameters=index
+  ##
+  """Returns the percentage of the vote given a response index. Note,
+  this script should be bound a poll by acquisition context."""
+  poll = context
+  return float(poll.getVotesFor(index)) / poll.getTotalVotes()
 
 
 Here's a DTML Method that displays poll results and allows you to
 vote::
 
-        <dtml-var standard_html_header>
+  <dtml-var standard_html_header>
 
-        <h2>
-          <dtml-var getQuestion>
-        </h2>
+  <h2>
+    <dtml-var getQuestion>
+  </h2>
 
-        <form> <!-- calls this dtml method -->
+  <form> <!-- calls this dtml method -->
 
-        <dtml-in getResponses>
-          <p>
-            <input type="radio" name="index" value="&dtml-sequence-index;">
-            <dtml-var sequence-item>
-          </p>
-        </dtml-in>
+  <dtml-in getResponses>
+    <p>
+      <input type="radio" name="index" value="&dtml-sequence-index;">
+      <dtml-var sequence-item>
+    </p>
+  </dtml-in>
 
-        <input type="submit" value=" Vote ">
+  <input type="submit" value=" Vote ">
 
-        </form>
+  </form>
 
-        <!-- process form -->
+  <!-- process form -->
 
-        <dtml-if index>
-          <dtml-call expr="castVote(index)">
-        </dtml-if>
+  <dtml-if index>
+    <dtml-call expr="castVote(index)">
+  </dtml-if>
 
-        <!-- display results -->
+  <!-- display results -->
 
-        <h2>Results</h2>
+  <h2>Results</h2>
 
-        <p><dtml-var getTotalVotes> votes cast</p>
+  <p><dtml-var getTotalVotes> votes cast</p>
 
-        <dtml-in getResponses>
-          <p>
-            <dtml-var sequence-item> -
-            <dtml-var expr="getPercentFor(_.get('sequence-index'))">%
-          </p>
-        </dtml-in>
+  <dtml-in getResponses>
+    <p>
+      <dtml-var sequence-item> -
+      <dtml-var expr="getPercentFor(_.get('sequence-index'))">%
+    </p>
+  </dtml-in>
 
-        <dtml-var standard_html_footer>
+  <dtml-var standard_html_footer>
 
-To use this DTML Method, call it on your poll instance. Notice how
+To use this DTML Method, call it on your poll instance.  Notice how
 this DTML makes calls to both your poll instance and the
-'getPercentFor' Python script.
+``getPercentFor`` Python script.
 
-
 At this point there's quite a bit of testing and refinement that you
-can do. Your main annoyance will be having to restart Zope each time
-you make a change to your product class (but see Chapter 7 for
-information on how to avoid all this restarting). If you vastly
+can do.  Your main annoyance will be having to restart Zope each time
+you make a change to your product class (but see Chapter 9 for
+information on how to avoid all this restarting).  If you vastly
 change your class you may break existing poll instances, and will
-need to delete them and create new ones. See Chapter 7 for more
+need to delete them and create new ones.  See Chapter 9 for more
 information on debugging techniques which will come in handy.
 
 Building Management Interfaces
@@ -723,42 +720,41 @@
 Defining Management Views
 -------------------------
 
-All Zope products can be managed through the web. Products have a
+All Zope products can be managed through the web.  Products have a
 collection of management tabs or *views* which allow managers to
 control different aspects of the product.
 
-A product's management views are defined in the 'manage_options'
-class attribute. Here's an example::
+A product's management views are defined in the ``manage_options``
+class attribute.  Here's an example::
 
         manage_options=(
             {'label' : 'Edit', 'action' : 'editMethod'},
             {'label' : 'View', 'action' : 'viewMethod'},
             )
 
-The 'manage_options' structure is a tuple that contains
-dictionaries. Each dictionary defines a management view. The view
+The ``manage_options`` structure is a tuple that contains
+dictionaries.  Each dictionary defines a management view.  The view
 dictionary can have a number of items.
 
-'label' -- This is the name of the management view
+- 'label' -- This is the name of the management view
 
-'action' -- This is the URL that is called when the view is
-chosen. Normally this is the name of a method that displays a
-management view.
+- 'action' -- This is the URL that is called when the view is
+  chosen. Normally this is the name of a method that displays a
+  management view.
 
-'target' -- An optional target frame to display the action. This item
-is rarely needed.
+- 'target' -- An optional target frame to display the action. This
+  item is rarely needed.
 
-'help' -- Optional help information associated with the view. You'll
-find out more about this option later.
+- 'help' -- Optional help information associated with the
+  view. You'll find out more about this option later.
 
+Management views are displayed in the order they are defined.
+However, only those management views for which the current user has
+permissions are displayed.  This means that different users may see
+different management views when managing your product.
 
-Management views are displayed in the order they are
-defined. However, only those management views for which the current
-user has permissions are displayed. This means that different users
-may see different management views when managing your product.
-
 Normally you will define a couple custom views and reusing some
-existing views that are defined in your base classes. Here's an
+existing views that are defined in your base classes.  Here's an
 example::
 
   class PollProduct(..., Item):
@@ -770,25 +766,25 @@
           ) + RoleManager.manage_options + Item.manage_options
 
 This example would include the standard management view defined by
-'RoleManager' which is *Security* and those defined by 'Item' which
-are *Undo* and *Ownership*. You should include these standard
+``RoleManager`` which is *Security* and those defined by ``Item``
+which are *Undo* and *Ownership*.  You should include these standard
 management views unless you have good reason not to. If your class
-has a default view method ('index_html') you should also include a
-*View* view whose action is an empty string. See Chapter 2 for more
-information on 'index_html'.
+has a default view method (``index_html``) you should also include a
+*View* view whose action is an empty string.  See Chapter 2 for more
+information on ``index_html``.
 
 Note: you should not make the *View* view the first view on your
-class. The reason is that the first management view is displayed when
-you click on an object in the Zope management interface. If the
+class.  The reason is that the first management view is displayed
+when you click on an object in the Zope management interface.  If the
 *View* view is displayed first, users will be unable to navigate to
 the other management views since the view tabs will not be visible.
 
 Creating Management Views
 -------------------------
 
-The normal way to create management view methods is to use DTML. You
-can use the 'DTMLFile' class to create a DTML Method from a file. For
-example::
+The normal way to create management view methods is to use DTML.  You
+can use the ``DTMLFile`` class to create a DTML Method from a file.
+For example::
 
   from Globals import DTMLFile
 
@@ -799,25 +795,24 @@
     ...
 
 This creates a DTML Method on your class which is defined in the
-'dtml/edit.dtml' file. Notice that you do not have to include the
-'.dtml' file extension. Also, don't worry about the forward slash as
-a path separator; this convention will work fine on Windows. By
-convention DTML files are placed in a 'dtml' subdirectory of your
-product. The 'globals()' argument to the 'DTMLFile' constructor
-allows it to locate your product directory. If you are running Zope
+`dtml/edit.dtml` file.  Notice that you do not have to include the
+``.dtml`` file extension.  Also, don't worry about the forward slash
+as a path separator; this convention will work fine on Windows. By
+convention DTML files are placed in a ``dtml`` subdirectory of your
+product.  The ``globals()`` argument to the ``DTMLFile`` constructor
+allows it to locate your product directory.  If you are running Zope
 in debug mode then changes to DTML files are reflected right away. In
 other words you can change the DTML of your product's views without
 restarting Zope to see the changes.
 
-
 DTML class methods are callable directly from the web, just like
-other methods. So now users can see your edit form by calling the
-'editForm' method on instances of your poll class. Typically DTML
+other methods.  So now users can see your edit form by calling the
+``editForm`` method on instances of your poll class.  Typically DTML
 methods will make calls back to your instance to gather information
-to display. Alternatively you may decide to wrap your DTML methods
-with normal methods. This allows you to calculate information needed
-by your DTML before you call it. This arrangement also ensures that
-users always access your DTML through your wrapper. Here's an
+to display.  Alternatively you may decide to wrap your DTML methods
+with normal methods.  This allows you to calculate information needed
+by your DTML before you call it.  This arrangement also ensures that
+users always access your DTML through your wrapper.  Here's an
 example::
 
   from Globals import DTMLFile
@@ -834,243 +829,240 @@
 
 
 When creating management views you should include the DTML variables
-'manage_page_header' and 'manage_tabs' at the top, and
-'manage_page_footer' at the bottom.  These variables are acquired by
-your product and draw a standard management view header, tabs
-widgets, and footer. The management header also includes CSS
+``manage_page_header`` and ``manage_tabs`` at the top, and
+``manage_page_footer`` at the bottom.  These variables are acquired
+by your product and draw a standard management view header, tabs
+widgets, and footer.  The management header also includes CSS
 information which you can take advantage of if you wish to add CSS
-style information to your management views. The management CSS
+style information to your management views.  The management CSS
 information is defined in the
-'lib/python/App/dtml/manage_page_style.css.dtml' file. Here are the
+`lib/python/App/dtml/manage_page_style.css.dtml`` file.  Here are the
 CSS classes defined in this file and conventions for their use.
 
-'form-help' -- Explanatory text related to forms. In the future,
-users may have the option to hide this text.
+- 'form-help' -- Explanatory text related to forms.  In the future,
+  users may have the option to hide this text.
 
-'std-text' -- Declarative text unrelated to forms. You should rarely
-use this class.
+- 'std-text' -- Declarative text unrelated to forms.  You should
+  rarely use this class.
 
-'form-title' -- Form titles.
+- 'form-title' -- Form titles.
 
-'form-label' -- Form labels for required form elements.
+- 'form-label' -- Form labels for required form elements.
 
-'form-optional' -- Form labels for optional form elements.
+- 'form-optional' -- Form labels for optional form elements.
 
-'form-element' -- Form elements. Note, because of a Netscape bug, you
-should not use this class on 'textarea' elements.
+- 'form-element' -- Form elements.  Note, because of a Netscape bug,
+  you should not use this class on 'textarea' elements.
 
-'form-text' -- Declarative text in forms.
+- 'form-text' -- Declarative text in forms.
 
-'form-mono' -- Fixed width text in forms. You should rarely use this
-class.
+- 'form-mono' -- Fixed width text in forms.  You should rarely use
+  this class.
 
-Here's an example management view for your poll class. It allows you
-to edit the poll question and responses (see 'editPollForm.dtml')::
+Here's an example management view for your poll class.  It allows you
+to edit the poll question and responses (see ``editPollForm.dtml``)::
 
-        <dtml-var manage_page_header>
-        <dtml-var manage_tabs>
+  <dtml-var manage_page_header>
+  <dtml-var manage_tabs>
 
-        <p class="form-help">
-        This form allows you to change the poll's question and
-        responses. <b>Changing a poll's question and responses
-        will reset the poll's vote tally.</b>.
-        </p>
+  <p class="form-help">
+  This form allows you to change the poll's question and
+  responses. <b>Changing a poll's question and responses
+  will reset the poll's vote tally.</b>.
+  </p>
 
-        <form action="editPoll">
-        <table>
+  <form action="editPoll">
+  <table>
 
-          <tr valign="top">
-            <th class="form-label">Question</th>
-            <td><input type="text" name="question" class="form-element"
-            value="&dtml-getQuestion;"></td>
-          </tr>
+    <tr valign="top">
+      <th class="form-label">Question</th>
+      <td><input type="text" name="question" class="form-element"
+      value="&dtml-getQuestion;"></td>
+    </tr>
 
-          <tr valign="top">
-            <th class="form-label">Responses</th>
-            <td><textarea name="responses:lines" cols="50" rows="10">
-            <dtml-in getResponses>
-            <dtml-var sequence-item html_quote>
-            </dtml-in>
-            </textarea>
-            </td>
-          </tr>
+    <tr valign="top">
+      <th class="form-label">Responses</th>
+      <td><textarea name="responses:lines" cols="50" rows="10">
+      <dtml-in getResponses>
+      <dtml-var sequence-item html_quote>
+      </dtml-in>
+      </textarea>
+      </td>
+    </tr>
 
-          <tr>
-            <td></td>
-            <td><input type="submit" value="Change" class="form-element"></td>
-          </tr>
+    <tr>
+      <td></td>
+      <td><input type="submit" value="Change" class="form-element"></td>
+    </tr>
 
-        </table>
-        </form>
+  </table>
+  </form>
 
-        <dtml-var manage_page_header>
+  <dtml-var manage_page_header>
 
 This DTML method displays an edit form that allows you to change the
-questions and responses of your poll. Notice how poll properties are
-HTML quoted either by using 'html_quote' in the 'dtml-var' tag, or by
-using the 'dtml-var' entity syntax.
+questions and responses of your poll.  Notice how poll properties are
+HTML quoted either by using ``html_quote`` in the ``dtml-var`` tag,
+or by using the ``dtml-var`` entity syntax.
 
+Assuming this DTML is stored in a file ``editPollForm.dtml`` in your
+product's ``dtml`` directory, here's how to define this method on
+your class::
 
-Assuming this DTML is stored in a file 'editPollForm.dtml' in your
-product's 'dtml' directory, here's how to define this method on your
-class::
+  class PollProduct(...):
+      ...
 
-        class PollProduct(...):
-            ...
+      security.declareProtected('View management screens', 'editPollForm')
+      editPollForm = DTML('dtml/editPollForm', globals())
 
-            security.declareProtected('View management screens', 'editPollForm')
-            editPollForm=DTML('dtml/editPollForm', globals())
-
-Notice how the edit form is protected by the 'View management
-screens' permission. This ensures that only managers will be able to
+Notice how the edit form is protected by the `View management
+screens` permission.  This ensures that only managers will be able to
 call this method.
 
-Notice also that the action of this form is 'editPoll'. Since the
+Notice also that the action of this form is ``editPoll``.  Since the
 poll as it stands doesn't include any edit methods you must define
-one to accept the changes. Here's an 'editPoll' method::
+one to accept the changes.  Here's an ``editPoll`` method::
 
-        class PollProduct(...):
-            ...
+  class PollProduct(...):
+      ...
 
-            def __init__(self, id, question, responses):
-                self.id=id
-                self.editPoll(question, response)
+      def __init__(self, id, question, responses):
+          self.id = id
+          self.editPoll(question, response)
 
-            ...
+      ...
 
-            security.declareProtected('Change Poll', 'editPoll')
-            def editPoll(self, question, responses):
-                """
-                Changes the question and responses.
-                """
-                self._question = question
-                self._responses = responses
-                self._votes = {}
-                for i in range(len(responses)):
-                    self._votes[i] = 0
+      security.declareProtected('Change Poll', 'editPoll')
+      def editPoll(self, question, responses):
+          """
+          Changes the question and responses.
+          """
+          self._question = question
+          self._responses = responses
+          self._votes = {}
+          for i in range(len(responses)):
+              self._votes[i] = 0
 
-Notice how the '__init__' method has been refactored to use the new
-'editPoll' method. Also notice how the 'editPoll' method is protected
-by a new permissions, 'Change Poll'.
+Notice how the ``__init__`` method has been refactored to use the new
+``editPoll`` method.  Also notice how the ``editPoll`` method is
+protected by a new permissions, ``Change Poll``.
 
-There still is a problem with the 'editPoll' method. When you call it
-from the 'editPollForm' through the web nothing is returned. This is
-a bad management interface. You want this method to return an HTML
-response when called from the web, but you do not want it to do this
-when it is called from '__init__'. Here's the solution::
+There still is a problem with the ``editPoll`` method.  When you call
+it from the ``editPollForm`` through the web nothing is returned.
+This is a bad management interface.  You want this method to return
+an HTML response when called from the web, but you do not want it to
+do this when it is called from ``__init__``.  Here's the solution::
 
-        class Poll(...):
-            ...
+  class Poll(...):
+      ...
 
-            def editPoll(self, question, responses, REQUEST=None):
-                """
-                Changes the question and responses.
-                """
-                self._question = question
-                self._responses = responses
-                self._votes = {}
-                for i in range(len(responses)):
-                    self._votes[i] = 0
-                if REQUEST is not None:
-                    return self.editPollForm(REQUEST,
-                        manage_tabs_message='Poll question and responses changed.')
+      def editPoll(self, question, responses, REQUEST=None):
+          """Changes the question and responses."""
+          self._question = question
+          self._responses = responses
+          self._votes = {}
+          for i in range(len(responses)):
+              self._votes[i] = 0
+          if REQUEST is not None:
+              return self.editPollForm(REQUEST,
+                  manage_tabs_message='Poll question and responses changed.')
 
 If this method is called from the web, then Zope will automatically
-supply the 'REQUEST' parameter. (See chapter 2 for more information
-on object publishing). By testing the 'REQUEST' you can find out if
-your method was called from the web or not. If you were called from
-the web you return the edit form again.
+supply the ``REQUEST`` parameter.  (See chapter 4 for more
+information on object publishing).  By testing the ``REQUEST`` you
+can find out if your method was called from the web or not.  If you
+were called from the web you return the edit form again.
 
 A management interface convention that you should use is the
-'manage_tab_message' DTML variable. If you set this variable when
+``manage_tab_message`` DTML variable.  If you set this variable when
 calling a management view, it displays a status message at the top of
-the page. You should use this to provide feedback to users indicating
-that their actions have been taken when it is not obvious. For
-example if you don't return a status message from your 'editPoll'
-method, users may be confused and may not realize that their changes
-have been made.
+the page.  You should use this to provide feedback to users
+indicating that their actions have been taken when it is not obvious.
+For example, if you don't return a status message from your
+``editPoll`` method, users may be confused and may not realize that
+their changes have been made.
 
 Sometimes when displaying management views, the wrong tab will be
-highlighted. This is because 'manage_tabs' can't figure out from the
-URL which view should be highlighted. The solution is to set the
+highlighted.  This is because 'manage_tabs' can't figure out from the
+URL which view should be highlighted.  The solution is to set the
 'management_view' variable to the label of the view that should be
-highlighted. Here's an example, using the 'editPoll' method::
+highlighted.  Here's an example, using the 'editPoll' method::
 
-        def editPoll(self, question, responses, REQUEST=None):
-            """
-            Changes the question and responses.
-            """
-            self._question = question
-            self._responses = responses
-            self._votes = {}
-            for i in range(len(responses)):
-                self._votes[i] = 0
-            if REQUEST is not None:
-                return self.editPollForm(REQUEST,
-                    management_view='Edit',
-                    manage_tabs_message='Poll question and responses changed.')
+  def editPoll(self, question, responses, REQUEST=None):
+      """
+      Changes the question and responses.
+      """
+      self._question = question
+      self._responses = responses
+      self._votes = {}
+      for i in range(len(responses)):
+          self._votes[i] = 0
+      if REQUEST is not None:
+          return self.editPollForm(REQUEST,
+              management_view='Edit',
+              manage_tabs_message='Poll question and responses changed.')
 
 Now let's take a look a how to define an icon for your product.
 
 Icons
 -----
 
-Zope products are identified in the management interface with
-icons. An icon should be a 16 by 16 pixel GIF image with a
-transparent background. Normally icons files are located in a 'www'
-subdirectory of your product package. To associate an icon with a
-product class, use the 'icon' parameter to the 'registerClass' method
-in your product's constructor. For example::
+Zope products are identified in the management interface with icons.
+An icon should be a 16 by 16 pixel GIF image with a transparent
+background.  Normally icons files are located in a ``www``
+subdirectory of your product package.  To associate an icon with a
+product class, use the ``icon`` parameter to the ``registerClass``
+method in your product's constructor.  For example::
 
-        def initialize(registrar):
-            registrar.registerClass(
-                PollProduct,
-                constructors=(addForm, addFunction),
-                icon='www/poll.gif'
-                )
+  def initialize(registrar):
+      registrar.registerClass(
+          PollProduct,
+          constructors=(addForm, addFunction),
+          icon='www/poll.gif'
+          )
 
 Notice how in this example, the icon is identified as being within
-the product's 'www' subdirectory.
+the product's ``www`` subdirectory.
 
-See the *API Reference* for more information on the 'registerClass'
-method of the 'ProductRegistrar' interface.
+See the *API Reference* for more information on the ``registerClass``
+method of the ``ProductRegistrar`` interface.
 
 Online Help
 -----------
 
 Zope has an online help system that you can use to provide help for
-your products. Its main features are context-sensitive help and API
-help. You should provide both for your product.
+your products.  Its main features are context-sensitive help and API
+help.  You should provide both for your product.
 
 
 Context Sensitive Help
 ----------------------
 
 To create context sensitive help, create one help file per management
-view in your product's 'help' directory. You have a choice of formats
-including: HTML, DTML, structured text, GIF, JPG, and PNG.
+view in your product's ``help`` directory.  You have a choice of
+formats including: HTML, DTML, structured text, GIF, JPG, and PNG.
 
 Register your help files at product initialization with the
-'registerHelp()' method on the registrar object::
+``registerHelp()`` method on the registrar object::
 
-          def initialize(registrar):
-              ...
-              registrar.registerHelp()
+  def initialize(registrar):
+      ...
+      registrar.registerHelp()
 
 This method will take care of locating your help files and creating
-help topics for each help file. It can recognize these file
-extensions: '.html', '.htm', '.dtml', '.txt', '.stx', '.gif', '.jpg',
-'.png'.
+help topics for each help file.  It can recognize these file
+extensions: ``.html``, ``.htm``, ``.dtml``, ``.txt``, ``.stx``,
+``.gif``, ``.jpg``, ``.png``.
 
 If you want more control over how your help topics are created you
-can use the 'registerHelpTopic()' method which takes an id and a help
-topic object as arguments. For example::
+can use the ``registerHelpTopic()`` method which takes an id and a
+help topic object as arguments.  For example::
 
-          from mySpecialHelpTopics import MyTopic
+  from mySpecialHelpTopics import MyTopic
 
-          def initialize(context):
-              ...
-              context.registerHelpTopic('myTopic', MyTopic())
+  def initialize(context):
+      ...
+      context.registerHelpTopic('myTopic', MyTopic())
 
 Your help topic should adhere to the 'HelpTopic' interface. See the
 *API Reference* for more details.
@@ -1079,16 +1071,16 @@
 include information about the help topic in the class's
 manage_options structure. For example::
 
-  manage_options=(
-      {'label':'Edit',
-       'action':'editMethod',
-       'help':('productId','topicId')},
+  manage_options = (
+      {'label': 'Edit',
+       'action': 'editMethod',
+       'help': ('productId','topicId')},
       )
 
-The 'help' value should be a tuple with the name of your product's
-Python package, and the file name (or other id) of your help
-topic. Given this information, Zope will automatically draw a *Help*
-button on your management screen and link it to your help topic.
+The `help` value should be a tuple with the name of your product's
+Python package, and the file name (or other id) of your help topic.
+Given this information, Zope will automatically draw a *Help* button
+on your management screen and link it to your help topic.
 
 To draw a help button on a management screen that is not a view (such
 as an add form), use the 'HelpButton' method of the 'HelpSys' object
@@ -1096,7 +1088,7 @@
 
   <dtml-var "HelpSys.HelpButton('productId', 'topicId')">
 
-This will draw a help button linked to the specified help topic. If
+This will draw a help button linked to the specified help topic.  If
 you prefer to draw your own help button you can use the helpURL
 method instead like so::
 
@@ -1153,7 +1145,7 @@
 Content Management Framework Interface
 --------------------------------------
 
-The `Content Management Framework <http://cmf.zope.org>` is an
+The `Content Management Framework <http://cmf.zope.org>`_ is an
 evolving content management extension for Zope.  It provides a number
 of interfaces and conventions for content objects.  If you wish to
 support the CMF you should consult the CMF user interface guidelines
@@ -1169,17 +1161,17 @@
 
 Zope products are normally packaged as tarballs.  You should create
 your product tarball in such a way as to allow it to be unpacked in
-the Products directory.  For example, 'cd' to the Products directory
-and then issue a 'tar' comand like so::
+the Products directory.  For example, `cd` to the Products directory
+and then issue a `tar` comand like so::
 
   $ tar zcvf MyProduct-1.0.1.tgz MyProduct
 
-This will create a gzipped tar archive containing your product. You
+This will create a gzipped tar archive containing your product.  You
 should include your product name and version number in file name of
 the archive.
 
-See the "Poll-1.0.tgz":examples/Poll-1.0.tgz file for an example of a
-fully packaged Python product.
+See the `Poll-1.0.tgz <examples/Poll-1.0.tgz>`_ file for an example
+of a fully packaged Python product.
 
 
 Product Information Files
@@ -1227,11 +1219,11 @@
 Some of these directories have already been discussed in this
 chapter. Here is a summary of them.
 
-  'www' -- Contains your icon & ZPT files.
+- `www` -- Contains your icon & ZPT files.
 
-  'help' -- Contains your help files.
+- `help` -- Contains your help files.
 
-  'tests' -- Contains your unit tests.
+- `tests` -- Contains your unit tests.
 
 It is not necessary to include these directories if your don't have
 anything to go in them.
@@ -1260,11 +1252,11 @@
 class so your old objects won't break when they run with your new
 class.  You might set 'improved_spam' to None in your class, and in
 methods where you use this attribute you may have to take into
-account that it may be None. For example::
+account that it may be None.  For example::
 
   class Sandwich(...):
 
-      improved_spam=None
+      improved_spam = None
       ...
 
       def assembleSandwichMeats(self):
@@ -1298,14 +1290,14 @@
 Evolving Interfaces
 -------------------
 
-The basic rule of evolving interfaces is *don't do it*. While you are
-working privately you can change your interfaces all you wish. But as
-soon as you make your interfaces public you should freeze them. The
-reason is that it is not fair to users of your interfaces to changes
-them after the fact. An interface is contract. It specifies how to
-use a component and it specifies how to implement types of
-components. Both users and developers will have problems if your
-change the interfaces they are using or implementing.
+The basic rule of evolving interfaces is *don't do it*.  While you
+are working privately you can change your interfaces all you wish.
+But as soon as you make your interfaces public you should freeze
+them.  The reason is that it is not fair to users of your interfaces
+to changes them after the fact.  An interface is contract.  It
+specifies how to use a component and it specifies how to implement
+types of components.  Both users and developers will have problems if
+your change the interfaces they are using or implementing.
 
 The general solution is to create simple interfaces in the first
 place, and create new ones when you need to change an existing
@@ -1313,8 +1305,8 @@
 interfaces you can indicate this by making your new interfaces extend
 your old ones.  If your new interface replaces an old one but does
 not extend it you should give it a new name such as,
-'WidgetWithBellsOn'.  Your components should continue to support the
-old interface in addition to the new one for a few releases.
+``WidgetWithBellsOn``.  Your components should continue to support
+the old interface in addition to the new one for a few releases.
 
 Conclusion
 ==========



More information about the checkins mailing list