[Checkins] SVN: zope3book/trunk/source/ Add few more chapter outlines

Baiju M baiju.m.mail at gmail.com
Fri Feb 20 14:10:15 EST 2009


Log message for revision 96847:
  Add few more chapter outlines
  

Changed:
  D   zope3book/trunk/source/InstallingZope3.rst
  D   zope3book/trunk/source/Preface.rst
  A   zope3book/trunk/source/browser-pages.rst
  A   zope3book/trunk/source/browser-resouces.rst
  A   zope3book/trunk/source/component-architecture.rst
  U   zope3book/trunk/source/conf.py
  A   zope3book/trunk/source/content-components.rst
  A   zope3book/trunk/source/development-tools.rst
  A   zope3book/trunk/source/getting-started.rst
  U   zope3book/trunk/source/index.rst
  A   zope3book/trunk/source/interfaces.rst
  A   zope3book/trunk/source/introduction.rst
  A   zope3book/trunk/source/skinning.rst
  A   zope3book/trunk/source/testing.rst

-=-
Deleted: zope3book/trunk/source/InstallingZope3.rst
===================================================================
--- zope3book/trunk/source/InstallingZope3.rst	2009-02-20 17:55:43 UTC (rev 96846)
+++ zope3book/trunk/source/InstallingZope3.rst	2009-02-20 19:10:14 UTC (rev 96847)
@@ -1,394 +0,0 @@
-Installing Zope 3
------------------
-
-
-Difficulty
-::::::::::
-
-Newcomer
-
-
-Skilla
-::::::
-
--   You should know how to use the command line of your operating system.
-    (For Windows releases, the Installer is provided.)
--   You need to know how to successfully install the latest version of
-    Python on your system.
-
-
-Problem/Task
-::::::::::::
-
-Before you can develop anything for Zope 3, you should, of course, install
-it.
-
-
-Solution
-::::::::
-
-
-Zope 3 Installation Requirements
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Zope 3 usually requires the latest stable Python version. For the Zope X3
-3.0.0 release, this is Python 2.3.4 or better. Note that you should always
-use the latest bug-fix release. Zope 3 does not require you to install or
-activate any special packages; the stock Python is fine. This has the great
-advantage that you can use a pre-packaged Python distribution (for example
-RPM, deb, Windows Installer) for your favorite operating system.
-
-Note: While distutils is part of the standard Python distribution, packagers
-often treat it as a separate installation package. In order to install Zope
-3, your Python must have distutils installed as well.
-
-The only catch is that Zope 3's C modules must be compiled with the same C
-compiler as Python. For example, if you install the standard Python
-distribution on Windows, which is compiled with Visual C++ 7, you cannot
-compile Zope 3's modules with Cygwin. However, this problem is not as bad as
-it seems. The Zope 3 binary distributions are always compiled with the same
-compiler as the standard Python distribution for the operating system.
-Furthermore, if you want to compile everything yourself, you are likely to
-use only one compiler anyway.
-
-On Unix/Linux your best bet is  `gcc`_. All Zope 3 developers are using
-`gcc`_, so it will always be supported. Furthermore, all Linux Python
-distribution packages are compiled using  `gcc`_. In Windows, the standard
-Python distribution is compiled using Visual C++ 7, as mentioned previously.
-Therefore the Zope 3 binary Windows release is also compiled with that
-compiler. However, people have also successfully used  `gcc`_ by using
-Cygwin, which comes with Python. Finally, you can run Zope 3 on MacOS X as
-well. All you need are  `gcc`_ and the  `make` program. With these, both
-Python and Zope 3 compile just fine.
-
-Python is available at the Python Web site (  `www.python.org`_).
-
-
-Installing Zope from SVN
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-In order to check out Zope 3 from SVN, you need to have a SVN client
-installed on your system. If you do not have a SVN account, you can use the
-anonymous user to check out a sandbox:
-
-
-1  svn co svn://svn.zope.org/repos/main/Zope3/trunk Zope3
-
-After the checkout is complete, you enter the Zope 3 directory:
-
-
-1  cd Zope3
-
-From there you run  `make` (so you need to have  `make` installed, and it
-should be available for all mentioned environments). If your Python
-executable is not called  `python2.3`_ and/or your Python binary is not in
-the path, you need to edit the first line of the  `Makefile`_ file to contain
-the correct path to the Python binary. Then you just run make, which
-builds/compiles Zope 3:
-
-
-1  make
-
-Next you copy  `sampleprincipals.zcml`_ to  `principals.zcml`_ and add a user
-with manager rights, as follows:
-
-
-1  <principal
-2      id="zope.userid" title="User Name Title"
-3      login="username" password="passwd" />
-4
-5  <grant role="zope.Manager" principal="zope.userid" />
-
-In the preceding code block, note the following:
-
--   Line 2: Notice that you do not need  `zope.`_ as part of your
-    principal ID, but the ID must contain at least one dot (  `.`_), because
-    that signals a valid ID.
--   Line 3: The login and password strings can be any random value, but
-    they must be correctly encoded for XML.
--   Line 5: If you do not use the default security policy, you might not
-    be able to use this  `zope:grant`_ directive because it might not support
-    roles. However, if you use the plain Zope 3 checkout, roles are available
-    by default.
-
-During development, you often do not want to worry about security. In such a
-case you can simply give  `anybody`_ the  `Manager`_ role:
-
-
-1  <grant role="zope.Manager" principal="zope.anybody" />
-
-The fundamental application server configuration can be found in
-`zope.conf`_. If  `zope.conf`_ is not available,  `zope.conf.in`_ is used
-instead. In this file you can define the types and ports of the servers you
-would like to activate, setup the ZODB storage type and specify logging
-options. The configuration file is very well documented, and making the
-desired changes should be easy.
-
-Now you are ready to start Zope 3 for the first time:
-
-
-1  ./bin/runzope
-
-The following output text should appear::
-
-  ------
-  2003-06-02T20:09:13 INFO PublisherHTTPServer zope.server.http (HTTP)
-   started.
-          Hostname: localhost
-          Port: 8080
-  ------
-  2003-06-02T20:09:13 INFO PublisherFTPServer zope.server.ftp started.
-          Hostname: localhost
-          Port: 8021
-  ------
-   2003-06-02T20:09:13 INFO root Startup time: 5.447 sec real, 5.190 sec
-     CPU
-
-After Zope comes up, you can test the servers by typing the following URL in
-your browser:  `http://localhost:8080/`_. You can test FTP by using
-`ftp://username@localhost:8021/`_. Even WebDAV is available using
-`webdav://localhost:8080/`_ in Konqueror or your favorite WebDAV client.
-
-An XML-RPC server is also built in to Zope by default, but most objects do
-not support any XML-RPC methods, so you cannot test it right away. Chapter
-"??" provides detailed instructions on how to use the XML-RPC server.
-
-
-Installing the Source Distribution
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-e following sections describe how to use the source TAR ball to compile and
-install a Zope 3 distribution.
-
-
-Unpacking the Package
-:::::::::::::::::::::
-
-The latest release of Zope 3 can be found at
-`www.zope.org/Products/ZopeX3`_. First, you need to download the latest Zope
-3 release by clicking the file that is available for all platforms, i.e.
-`ZopeX3-VERSION.tgz`_. You can use  `tar`_ or WinZip to extract the archive,
-like this:
-
-
-1  tar xzf ZopeX3-3.0.0.tgz
-
-
-Building Zope
-:::::::::::::
-
-For Zope 3 releases, distributation makers provided the well-known
-`configure`_/  `make` procedure. So you can start the configuration process
-by using the following after you have entered the newly created directory:
-
-
-1  ./configure
-
-If you want to place the binaries of the distribution somewhere other than
-`/usr/local/ZopeX3-VERSION`_, you can specify the  `-prefix`_ option as
-usual. Also, if you have Python installed at a non-standard location, you can
-specify the Python executable by using  `-with-python`_. A full configuration
-statement could look like this:
-
-
-1  ./configure --prefix=/opt/Zope3 --with-
-    python=/opt/puython2.3/bin/python2.3
-
-The following output is immediately returned:
-
-
-1  Configuring Zope X3 installation
-2
-3  Using Python interpreter at /opt/puython2.3/bin/python2.3
-
-Now that the source has been configured, you can build it by using  `make`.
-After you enter the  `make` command, the following line is returned:
-
-
-1  /opt/python2.3/bin/python2.3 install.py -q build
-
-The hard drive is busy for several minutes, compiling the source. When the
-command line returns, you can run the tests by using the following:
-
-
-1  make check
-
-Here, both the unit and functional tests are executed. For each executed
-test, you have one dot on the screen. The check takes between 5 and 10
-minutes depending on the speed and free cycles on your computer. The final
-output should look as follows::
-
-
-  Python2.3 install.py -q build
-  Python2.3 test.py -v
-  Running UNIT tests at level 1
-  Running UNIT tests from
-   /path/to/ZopeX3-VERSION/build/lib.linux-i686-2.3
-  [some 4000+ dots]
-  ----------------------------------------------------------------------
-  Ran 3896 tests in 696.647s
-
-  OK
-
-The exact number of tests run depends on the version of Zope, the operating
-system, and the host platform. If the last line displays  `OK`_, you know
-that all tests passed. After you have verified the check, you can install the
-distribution as follows:
-
-
-1  make install
-
-Note: You have to have the correct permissions to create the installation
-directory and copy the files into it. Thus, it might be useful to become root
-to execute the command.
-
-
-Creating a Zope Instance
-::::::::::::::::::::::::
-
-When the installation is complete, Zope is available in the directory you
-specified in  `-prefix`_ or under  `/usr/local/ZopeX3-VERSION`_. However,
-Zope will not yet run, because you have not created an instance yet. You use
-instances when you want to host several Zope-based sites, using the same base
-software configuration.
-
-Creating a new instance is easy. You enter the Zope 3 installation directory
-and enter the following command:
-
-
-1  /bin/mkzopeinstance -u username:password -d path/to/instance
-
-This creates a Zope 3 instance in  `path/to/instance`_. A user who has the
-login  `username`_ and password  `password`_ is created for you, and the
-`zope.manager`_ role is assigned to it. All the configuration for the created
-instance are available in the  `path/to/instance/etc`_ directory. You need to
-review all the information in there to ensure that it fits your needs.
-
-
-Running Zope
-::::::::::::
-
-You execute Zope by calling
-
-
-1  ./bin/runzope
-
-from the instance directory. The startup output will be equal to that of the
-source Zope SVN installation.
-
-You are all done now! When the server is up and running, you can test it via
-you favorite browser, as described earlier in this chapter.
-
-
-Installing the Source Distribution in Windows Without Using make
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Installing the source distribution on Windows is possible even without
-`make`. However, you need a supported C compiler to build the package. If
-you do not have a C compiler or Cygwin installed, you can use the Windows
-Installer to install Zope 3. (See the next section for more details.)
-
-Before installing Zope 3, you need to install Python 2.3.4 or higher. On
-Windows NT/2000/XP the extension  `.py`_ is automatically associated with the
-Python executable, so you do not need to specify the Python executable when
-running a script.
-
-After you unpack the distribution, you enter the directory. You build the
-software by using this:
-
-
-1  install.py -q build
-
-When the build process is complete, you can run the tests with this:
-
-
-1  test.py -v
-
-This should give you the same output as under Unix/Linux. After the tests are
-verified, you install the distribution by using the following command:
-
-
-1  install.py -q install
-
-You have now completed the installation of Zope 3. Now you can follow the
-final steps in the previous section to create an instance and start up Zope.
-
-Note: When you install Zope 3 in Windows without using  `make`, it's really
-hard to uninstall it later, because you have to manually delete files and
-directories from various locations, including your Python's  `Lib/site-
-packages"` and  `Scripts` directories. You also have to completely remove
-the  `zopeskel` directory. If you use Windows Installer instead, an
-uninstallation program is provided and registered in the Control Panel's
-Add/Remove Programs applet.
-
-
-Installing the Binary Distribution of Zope
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Currently binary releases of Zope are available only for Windows. These
-releases assume that you have the standard Windows Python release installed.
-The Windows binary release is an executable that automatically executes
-Windows Installer. The first task is to make sure that you have the correct
-Python version installed. Zope X3.0 is released to work with Python 2.3.
-Thus, you need to install the latest Python 2.3 bug fix release. You can get
-the Windows binary installer at  `www.python.org/download/`_.
-
-If you already have a previous version of Zope X3, you need to remove it by
-using Add/Remove Programs from the Control Panel. Then you can install the
-Zope X3.0 release, which you can find at  `dev.zope.org/Zope3/Downloads`_.
-After you download it, you simply execute the installer and follow its
-instructions.
-
-When the install is complete, you need to open a Windows command prompt and
-change to the root Python 2.3 directory, usually  `C:\python23`. Then you
-execute the instance creation script using this:
-
-
-1  .\python .\Scripts\mkzopeinstance -u username:password -d
-    c:\path\to\instance
-
-This completes the installation. You can now run Zope 3 by using this:
-
-
-1  .\python c:\path\to\instance\bin\runzope
-
-The instance's  `bin`_ directory also contains some other useful scripts,
-such as the test runner.
-
-You can later use the Control Panel's Add/Remove Programs applet to uninstall
-Zope 3 again.
-
-.. _gcc: gcc
-.. _www.python.org: www.python.org
-.. _python2.3: python2.3
-.. _Makefile: Makefile
-.. _sampleprincipals.zcml: sample_principals.zcml
-.. _principals.zcml: principals.zcml
-.. _zope.: zope.
-.. _.: .
-.. _zope:grant: zope:grant
-.. _anybody: anybody
-.. _Manager: Manager
-.. _zope.conf: zope.conf
-.. _zope.conf.in: zope.conf.in
-.. _http://localhost:8080/: http://localhost:8080/
-.. _ftp://username@localhost:8021/: ftp://username@localhost:8021/
-.. _webdav://localhost:8080/: webdav://localhost:8080/
-.. _www.zope.org/Products/ZopeX3: www.zope.org/Products/ZopeX3
-.. _ZopeX3-VERSION.tgz: ZopeX3-VERSION.tgz
-.. _tar: tar
-.. _configure: configure
-.. _/usr/local/ZopeX3-VERSION: /usr/local/ZopeX3-VERSION
-.. _-prefix: --prefix
-.. _-with-python: --with-python
-.. _OK: OK
-.. _path/to/instance: path/to/instance
-.. _username: username
-.. _password: password
-.. _zope.manager: zope.manager
-.. _path/to/instance/etc: path/to/instance/etc
-.. _.py: .py
-.. _www.python.org/download/: www.python.org/download/
-.. _dev.zope.org/Zope3/Downloads: dev.zope.org/Zope3/Downloads
-.. _python23: c:\python23\
-.. _bin: bin

Deleted: zope3book/trunk/source/Preface.rst
===================================================================
--- zope3book/trunk/source/Preface.rst	2009-02-20 17:55:43 UTC (rev 96846)
+++ zope3book/trunk/source/Preface.rst	2009-02-20 19:10:14 UTC (rev 96847)
@@ -1,202 +0,0 @@
-Preface
--------
-
-.. note:: This is the preface of the original book.  We need to
-  create another preface for the new version.
-
-The preface will be a brief introduction into Zope 3 and its capabilities as
-well as into Python , the programming language Zope is written in.
-
-What is Zope?
-~~~~~~~~~~~~~
-
-What is Zope? While this sounds like a simple question that should be
-answered in a line or two, I often find myself in situations where I am
-unable to simple say: "It is an Open-Source Application Server." or "It is a
-Content Management System.". Both of these descriptions are true, but they
-are really putting a limit on Zope that simply does not exist. So before I
-will give my definition of Zope, let's collect some of the solutions Zope has
-been used for. As mentioned above, many people use Zope as a Content
-Management System, which are usually Web-based (browser managed) systems.
-Basically the users can manage the content of a page through a set of Web
-forms, workflows and editing tools. However, there is an entirely different
-CMS genre, for which Zope also has been used. Other companies, such as
-struktur AG, used Zope successfully to interface with the XML Database Tamino
-(from software AG). The second common use is Zope as a Web-Application
-server, where it is used to build Web-based applications, such as online
-shops or project management tools. Of course, Zope is also suitable for
-regular Web sites.
-
-And yet, there is a usage that we neglected so far. Zope can also be used as
-a reliable backend server managing the logistics of a company's operations.
-In fact, bluedynamics.com in Austria built a logistic software based on Zope
-2 ZClasses and a relational database that was able to handle hundreds of
-thousands transactions each day from taking credit card information and
-billing the customer up to ordering the products from the warehouse using
-XML-RPC. In my opinion this is the true strength of Zope, since it allows not
-only Web-familiar protocols to talk to, but also any other network protocol
-you can imagine. Zope 3, with its component architecture, accelerates even
-more in this area, since third party products can be easily plugged in or
-even replace some of the defaults. For example the Twisted framework can
-replace all of ZServer (the Zope Server components).
-
-Now that we have seen some of the common and uncommon uses of Zope it might
-be possible to formulate a more formal definition of Zope, just in case you
-are being asked at one point. Zope is an application and backend server
-framework that allows developers to quickly implement protocols, build
-applications (usually Web-based) and function as glue among other net-enabled
-services.
-
-Before Zope was developed, Zope Corporation was reviewing many possible
-programming languages to develop the framework, such as Java, C/C++, Perl and
-Python. After extensive research they found that only Python would give them
-the competitive advantage in comparison to the other large framework
-providers, such as IBM, BEA and others.
-
-
-Powerful Python
-~~~~~~~~~~~~~~~
-
-Python is a high-level object-oriented scripting language producing - by
-design - clean code through mandatory indentation. While Perl is also an
-interpreted scripting language, it lacks the cleanness and object-orientation
-of Python. Java, on the other hand, provides a nice object-oriented approach,
-but fails to provide powerful tools to build applications in a quick manner.
-So it is not surprising that Python is used in a wide variety of real world
-situations, like NASA, which uses Python to interpret their simulation data
-and connect various small C/C++ programs. Also, Mailman, the well-known
-mailing list manager, is being developed using Python. On the other hand, you
-have academics that use this easy-to-learn language for their introductory
-programming courses.
-
-Since Python is such an integral part of the understanding of Zope, you
-should know it well. If you are looking for some introductory documentation,
-you should start with the tutorial that is available directly from the Python
-homepage `http://www.python.org/doc/current/tut/tut.html`_. Also, there are a
-wide variety of books published by almost every publisher.
-
-
-In the beginning there was...
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Every time I am being asked to give a presentation or write a survey-like
-article about Zope, I feel the need to tell a little bit about its history,
-not only because it is a classic Open-Source story, but also because it gives
-some background on why the software behaves the way it does. So it should
-definitely not be missing here.
-
-Before Zope was born, Zope Corporation (which was originally named Digital
-Creations) developed and distributed originally three separate products
-called Bobo, Principia and Aqueduct. Bobo was an object publisher written in
-Python, which allowed one to publish objects as pages on the web. It also
-served as object database and object request broker (ORB), converting URLs
-into object paths. Most of this base was implemented by Jim Fulton in 1996
-after giving a frustrating Python CGI tutorial at the International Python
-Conference. Even though Bobo was licensed under some sort of "free" license,
-it was not totally Open-Source and Principia was the commercial big brother.
-
-In 1998, Hadar Pedhazur, a well-known venture capitalist, convinced Digital
-Creations to open up their commercial products and publish them as Open
-Source under the name Zope. Zope stands for the "Z Object Publishing
-Environment". The first Zope release was 1.7 in December 1998. Paul Everitt,
-former CEO, and all the other people at Zope Corporation converted from a
-product company into a successful consultant firm. Alone the story how Zope
-Corporation went from a proprietary, product-based to a service-based company
-is very interesting, but is up to someone else to tell.
-
-In the summer of 1999, Zope Corporation published version 2.0, which will be
-the base for the stable release until Zope 3.0 will outdate it in the next
-few years. Zope gained a lot of popularity with the 2.x series; it is now
-included in all major Linux distributions and many books have been written
-about it. Originally I was going to write this book on the Zope 2.x API, but
-with the beginning of the Zope 3.x development in late 2001, it seemed much
-more useful to do the documentation right this time and write an API book
-parallel to the development itself. In fact when these lines were originally
-written, there was no Zope Management Interface , and the initial security
-had just been recently implemented.
-
-
-Zope 3 Components
-~~~~~~~~~~~~~~~~~
-
-Zope 3 will make use of many of the latest and hottest development patterns
-and technologies, and that with "a twist" as Jim Fulton likes to describe it.
-But Zope 3 also reuses some of the parts that were developed for previous
-versions. Users will be glad to find that Acquisition (but in a very
-different form) is available again as well as Zope Page Templates and the
-Document Template Markup Language - DTML (even though with less emphasis).
-Also, there is the consensus of a Zope Management Interface in Zope 3 again,
-but is completely developed from scratch in a modular fashion so that
-components cannot be only reused, but the entire GUI can be altered as
-desired.
-
-But not only DTML, ZPT and Aquidition received a new face in Zope 3; external
-data handling has been also totally reworked to make external data play
-better together with the internal persistence framework, so that the system
-can take advantage of transactions, and event channels. Furthermore, the
-various external data sources are now handled much more generically and are
-therefore more transparent to the developer. But which external data sources
-are supported? By default Zope 3 comes with a database adaptor for Gadfly ,
-but additional adapters for PostGreSQL and other databases already exist and
-many others will follow. Data sources that support XML-RPC, like the very
-scalable XML database Tamino, could also be seamlessly inserted. However, any
-other imaginable data source can be connected to Zope by developing a couple
-of Python modules, as described in various chapters.
-
-During the last five years (the age of Zope 2) not only Zope was developed
-and improved, but also many third party products were written by members of
-the very active Zope community for their everyday need. These products range
-from Hot Fixes, Database Adaptors and Zope objects to a wide range of end
-user software, such as e-commerce, content management and e-learning systems.
-However, some of these products turned out to be generically very useful to a
-wide variety of people; actually, they are so useful, that they were
-incorporated into the Zope 3 core. The prime examples are the two
-internationalization and localization tools Localizer (by Juan David Iba?ez
-Palomar) and ZBabel (by me), whose existence shaped the implementation of the
-internationalization and localization support Zope 3 significantly. Another
-great product that made it into the Zope 3 core was originally written by
-Martijn Faassen and is called Formulator. Formulator allows the developer to
-define fields (representing some meta-data of a piece of content) that
-represent data on the one side and HTML fields on the other. One can then
-combine fields to a form and have it displayed on the Web. The second great
-feature Formulator came with was the Validator, which validated user-entered
-data on the server side. Formulator's concepts were modularized into schemas
-and forms/widgets  and incorporated in Zope 3.
-
-Altogether, the framework is much cleaner now (and more pythonic) and
-features that failed to make it into the Zope 2 core were incorporated.
-
-
-Goals of this book
-~~~~~~~~~~~~~~~~~~
-
-The main target audience for this book are developers that would like to
-develop on the Zope 3 framework itself; these are referred to as Zope
-developers in this book. But also Python programmers will find many of the
-chapters interesting, since they introduce concepts that could be used in
-other Python applications as well. Python programmers could also use this
-book as an introduction to Zope.
-
-In general the chapters have been arranged in a way so that the Zope 3
-structure itself could be easily understood. The book starts out by getting
-you setup, so that you can evaluate and develop with Zope 3. The second part
-of the book consists of chapters that are meant as introductions to various
-important concepts of Zope 3. If you are a hands-on developer like me, you
-might want to skip this part until you have done some development. The third
-and fourth part are the heart of the book, since a new content component with
-many features is developed over a course of 12 chapters. Once you understand
-how to develop content components, part five has a set of chapters that
-introduce other components that might be important for your projects. The
-fifth part is intended for people that wish to use Zope technologies outside
-of Zope 3. The emphasis on testing is one of the most important philosophical
-transitions the Zope 3 development team has undergone. Thus the last chapter
-is dedicated to various ways to write tests.
-
-Last but not least this book should encourage you to start helping us to
-develop Zope 3. This could be in the form of enhancing the Zope 3 core itself
-or by developing third party products, reaching from new content objects to
-entire applications, such as an e-commerce system. This book covers all the
-modules and packages required for you to start developing.
-
-.. _http://www.python.org/doc/current/tut/tut.html:
-    http://www.python.org/doc/current/tut/tut.html

Added: zope3book/trunk/source/browser-pages.rst
===================================================================
--- zope3book/trunk/source/browser-pages.rst	                        (rev 0)
+++ zope3book/trunk/source/browser-pages.rst	2009-02-20 19:10:14 UTC (rev 96847)
@@ -0,0 +1,61 @@
+Browser Pages
+=============
+
+In the last chapter we have seen how to use resources HTML.  The
+resource HTML will be only available on site-level with the `\@\@`
+prefix.
+
+Browser page (or more generically views) are representations for
+particular objects/components.
+
+If you have a template like this (helloworld.pt)::
+
+  Hello, World !
+
+Here is how to register a page for IFolder interface::
+
+  <browser:page
+    name="helloworld.html"
+    for="zope.app.folder.interfaces.IFolder"
+    template="helloworld.pt"
+    permission="zope.Public"
+    /> 
+
+
+View components
+---------------
+
+While templates display data view components are preparing data.
+View components convert data to output formats also prepare related
+data (meta-data).  Then, create TAL-friendly object structures (dicts
+and lists).  View components know about: component for which the
+representation is created (context) and request object holding all
+`output media` information (request)
+
+
+Implementation
+~~~~~~~~~~~~~~
+
+Normally view components are added inside `browser` package inside
+your main package.  The organization of the browser code is really up
+to you and the above examples are just the most basic rules of thumb.
+
+Here is simple view defined::
+
+  from zope.publisher.browser import BrowserPage
+  from zope.app.folder import interfaces
+
+  class HelloWorld(BrowserPage):
+
+      def subFolderIds(self):
+          for name, subobj in self.context.items():
+              if interfaces.IFolder.providedBy(subobj):
+                  yield name 
+
+Since methods and attributes of the view component are directly used
+by the template, they should return simple iterable objects
+(e.g. lists, tuples, generators) or mappings (e.g. dicts).
+
+
+View components - integration
+-----------------------------

Added: zope3book/trunk/source/browser-resouces.rst
===================================================================
--- zope3book/trunk/source/browser-resouces.rst	                        (rev 0)
+++ zope3book/trunk/source/browser-resouces.rst	2009-02-20 19:10:14 UTC (rev 96847)
@@ -0,0 +1,149 @@
+Browser Resources
+=================
+
+
+File Resource
+-------------
+
+Certain presentation, like images and style sheets are not associated
+with any other component, so that one cannot create a view.  To solve
+this problem, resources were developed, which are presentation
+components that do not require any context.  This mini-chapter will
+demonstrate how resources are created and registered with Zope 3.
+
+The first goal is to register a simple plain-text file called
+`resource.txt` as a browser resource.  The first step is to create
+this file anywhere you wish on the filesystem, and adding the
+following content::
+
+  Hello, I am a Zope 3 Resource Component!
+
+Now just register the resource in a ZCML configuration file using the
+`browser` resource directive::
+
+  <browser:resource
+    name="resource.txt"
+    file="resource.txt"
+    layer="default"
+    />
+
+Line 2: This is the name under which the resource will be known in
+Zope.
+
+Line 3: The file attribute specifies the path to the resource on the
+filessytem.  The current working directory ('.') is always the
+directory the configuration file is located.  So in the example
+above, the file `resource.txt` is located in the same folder as the
+configuration file is.
+
+Line 4: The optional layer attribute specifies the layer the resource
+is added to.  By default, the default layer is selected.
+
+Once you hook up the configuration file to the main configuration
+path and restart Zope 3, you should be able to access the resource
+now via a Browser using `http://localhost:8080/@@/resource.txt`.  The
+`@@/` in the URL tells the traversal mechanism that the following
+object is a resource.
+
+
+Image resource
+--------------
+
+If you have an image resource, you might want to use different
+configuration.  Create a simple image called img.png and register it
+as follows::
+
+  <browser:resource
+    name="img.png"
+    image="img.png"
+    permission="zope.ManageContent"
+    />
+
+Line 3: As you can see, instead of the `file` attribute we use the
+`image` one.  Internally this will create an `Image` object, which is
+able to detect the content type and returns it correctly.  There is a
+third possible attribute named `template`.  If specified, a Page
+Template that is executed when the resource is called.  Note that
+only one of `file`, `image`, or `template` attributes can be
+specified inside a resource directive.
+
+Line 4: A final optional attribute is the ''permission'' one must
+have to view the resource.  To demonstrate the security, I set the
+permission required for viewing the image to `zope.ManageContent`, so
+that you must log in as an administrator/- manager to be able to view
+it.  The default of the attribute is `zope.Public` so that everyone
+can see the resource.
+
+
+Directory resource
+------------------
+
+If you have many resource files to register, it can be very tedious
+to write a single directive for every resource.  For this purpose the
+`resourceDirectory` is provided, with which you can simply declare an
+entire directory, including its content as resources.  Thereby the
+filenames of the files are reused as the names for the resource
+available.  Assuming you put your two previous resources in a
+directory called resource, then you can use the following::
+
+  <browser:resourceDirectory
+    name="resources"
+    directory="../resource"
+    />
+
+The image will then be publically available under the URL:
+`http://localhost:8080/@@/resources/img.png`
+
+The `DirectoryResource` object uses a simple resource type
+recognition.  It looks at the filename extensions to discover the
+type.  For page templates, currently the extensions ''pt'', ''zpt''
+and ''html'' are registered and for an image ''gif'', ''png'' and
+''jpg''.  All other extensions are converted to file resources.  Note
+that it is not necessary to have a list of all image types, since
+only Browser-displayable images must be recognized.
+
+
+ZRT resource
+------------
+
+When working locally, you may be storing your image resources in a
+directory.  If you have a subfolder called `images` with an image
+`logo.png`.  And you have a template, so here is the HTML to insert
+the logo::
+
+  <img src="./images/logo.png" />
+
+Now you can see that the template locally works.
+
+If you view the HTML via Zope, you can see that it is broken.
+
+Now, let's try to register the logo with the system like this::
+
+  <resource
+    name="logo.png"
+    file="images/logo.png"
+    />
+
+Now try again, after restarting Zope 3, you can see that it is still
+broken!.  So, relative path is not correct.
+
+Zope Resource Templates (ZRT) allows for locally working resources to
+work with Zope 3 as well.  It will rewrite text segments in a
+resource.  It is a 3rd party package developed by Stephan Richter for
+Lovely Systems.  The package is available from here:
+`http://pypi.python.org/pypi/z3c.zrtresource`
+
+To use the zrt-resource add the following lines to the page
+template::
+
+  <!--
+    /* zrt-replace: "./images/logo.png" \
+                    tal"string:${context/++resource++logo.png}" */
+  -->
+
+Then convert HTML resource registration to::
+
+  <zrt-resource
+    name="helloworld.html"
+    file="helloworld.html"
+    />

Added: zope3book/trunk/source/component-architecture.rst
===================================================================
--- zope3book/trunk/source/component-architecture.rst	                        (rev 0)
+++ zope3book/trunk/source/component-architecture.rst	2009-02-20 19:10:14 UTC (rev 96847)
@@ -0,0 +1,407 @@
+Component Architecture
+======================
+
+`Zope Component Architecture (ZCA)` is a framework for supporting
+component based design and programming.  It is very well suited to
+developing large Python software systems.  The ZCA is not specific to
+the Zope web application server: it can be used for developing any
+Python application.
+
+The ZCA is all about using Python objects effectively.  Components
+are reusable objects with introspectable interfaces.  A component
+provides an interface implemented in a class, or any other callable
+object.  It doesn't matter how the component is implemented, the
+important part is that it comply with its interface contracts.  Using
+ZCA, you can spread the complexity of systems over multiple
+cooperating components.  It helps you to create two basic kinds of
+components: `adapter` and `utility`.
+
+There are two core packages related to the ZCA:
+
+* `zope.interface` is used to define the interface of a component.
+
+* `zope.component` deals with registration and retrieval of
+  components.
+
+Remember, the ZCA is not about the components themselves, rather it
+is about creating, registering, and retrieving components.  Remember
+also, an `adapter` is a normal Python class (or a factory in general)
+and `utility` is a normal Python callable object.
+
+The ZCA framework is developed as part of the Zope 3 project.  As
+noted earlier, it is a pure Python framework, so it can be used in any
+kind of Python application.  Currently both Zope 3 and Zope 2 projects
+use this framework extensively.  There are many other projects
+including non-web applications using it.
+
+Installation
+------------
+
+Using `zc.buildout` with `zc.recipe.egg` recipe you can create Python
+interpreter with specified Python eggs.  First you can create a
+directory and initialize Buildout::
+
+  $ mkdir explore-zope.component
+  $ cd explore-zope.component
+  $ echo "#Buildout configuration" > buildout.cfg
+  $ svn co svn://svn.zope.org/repos/main/zc.buildout/trunk/bootstrap
+  $ ~/usr/bin/python2.4 bootstrap/bootstrap.py
+
+Now modify the `buildout.cfg` like this::
+
+  [buildout]
+  parts = py
+
+  [py]
+  recipe = zc.recipe.egg
+  eggs = zope.component
+  interpreter = mypython
+
+Now run `buildout` script inside `bin` directory.  This will download
+zope.component and its dependency eggs and install it.  Now you can
+access the interpreter created by the Buildout recipe like this::
+
+  $ ./bin/buildout
+  $ ./bin/mypython
+  >>> import zope.component
+
+Adapters
+--------
+
+
+Implementation
+~~~~~~~~~~~~~~
+
+This section will describe adapters in detail.  Zope component
+architecture, as you noted, helps to effectively use Python objects.
+Adapter components are one of the basic components used by Zope
+component architecture for effectively using Python objects.  Adapter
+components are Python objects, but with well defined interface.
+
+To declare a class is an adapter use `adapts` function defined in
+`zope.component` package.  Here is a new `FrontDeskNG` adapter with
+explicit interface declaration::
+
+  >>> from zope.interface import implements
+  >>> from zope.component import adapts
+
+  >>> class FrontDeskNG(object):
+  ...
+  ...     implements(IDesk)
+  ...     adapts(IGuest)
+  ...
+  ...     def __init__(self, guest):
+  ...         self.guest = guest
+  ...
+  ...     def register(self):
+  ...         guest = self.guest
+  ...         next_id = get_next_id()
+  ...         bookings_db[next_id] = {
+  ...         'name': guest.name,
+  ...         'place': guest.place,
+  ...         'phone': guest.phone
+  ...         }
+
+What you defined here is an `adapter` for `IDesk`, which adapts
+`IGuest` object.  The `IDesk` interface is implemented by
+`FrontDeskNG` class.  So, an instance of this class will provide
+`IDesk` interface.
+
+::
+
+  >>> class Guest(object):
+  ...
+  ...     implements(IGuest)
+  ...
+  ...     def __init__(self, name, place):
+  ...         self.name = name
+  ...         self.place = place
+
+  >>> jack = Guest("Jack", "Bangalore")
+  >>> jack_frontdesk = FrontDeskNG(jack)
+
+  >>> IDesk.providedBy(jack_frontdesk)
+  True
+
+The `FrontDeskNG` is just one adapter you created, you can also
+create other adapters which handles guest registration differently.
+
+
+Registration
+~~~~~~~~~~~~
+
+To use this adapter component, you have to register this in a
+component registry also known as site manager.  A site manager
+normally resides in a site.  A site and site manager will be more
+important when developing a Zope 3 application.  For now you only
+required to bother about global site and global site manager ( or
+component registry).  A global site manager will be in memory, but a
+local site manager is persistent.
+
+To register your component, first get the global site manager::
+
+  >>> from zope.component import getGlobalSiteManager
+  >>> gsm = getGlobalSiteManager()
+  >>> gsm.registerAdapter(FrontDeskNG,
+  ...                     (IGuest,), IDesk, 'ng')
+
+To get the global site manager, you have to call
+`getGlobalSiteManager` function available in `zope.component`
+package.  In fact, the global site manager is available as an
+attribute (`globalSiteManager`) of `zope.component` package.  So, you
+can directly use `zope.component.globalSiteManager` attribute.  To
+register the adapter in component, as you can see above, use
+`registerAdapter` method of component registry.  The first argument
+should be your adapter class/factory.  The second argument is a tuple
+of `adaptee` objects, i.e, the object which you are adapting.  In
+this example, you are adapting only `IGuest` object.  The third
+argument is the interface implemented by the adapter component.  The
+fourth argument is optional, that is the name of the particular
+adapter.  Since you gave a name for this adapter, this is a `named
+adapter`.  If name is not given, it will default to an empty string
+('').
+
+In the above registration, you have given the adaptee interface and
+interface to be provided by the adapter.  Since you have already
+given these details in adapter implementation, it is not required to
+specify again.  In fact, you could have done the registration like
+this::
+
+  >>> gsm.registerAdapter(FrontDeskNG, name='ng')
+
+There are some old API to do the registration, which you should
+avoid.  The old API functions starts with `provide`, eg:
+`provideAdapter`, `provideUtility` etc.  While developing a Zope 3
+application you can use Zope configuration markup language (ZCML) for
+registration of components.  In Zope 3, local components (persistent
+components) can be registered from Zope Management Interface (ZMI) or
+you can do it programmatically also.
+
+You registered `FrontDeskNG` with a name `ng`.  Similarly you can
+register other adapters with different names.  If a component is
+registered without name, it will default to an empty string.
+
+
+Querying adapter
+~~~~~~~~~~~~~~~~
+
+Retrieving registered components from component registry is achieved
+through two functions available in `zope.component` package.  One of
+them is `getAdapter` and the other is `queryAdapter`.  Both functions
+accepts same arguments.  The `getAdapter` will raise
+`ComponentLookupError` if component lookup fails on the other hand
+queryAdapter will return `None`.
+
+You can import the methods like this::
+
+  >>> from zope.component import getAdapter
+  >>> from zope.component import queryAdapter
+
+In the previous section you have registered a component for guest
+object (adaptee) which provides `IDesk` interface with name as `ng`.
+In the first section of this chapter, you have created a guest object
+named `jack`.
+
+This is how you can retrieve a component which adapts the interface
+of jack object (`IGuest`) and provides `IDesk` interface also
+with name as `ng`.  Here both `getAdapter` and
+`queryAdapter` works similarly::
+
+  >>> getAdapter(jack, IDesk, 'ng') #doctest: +ELLIPSIS
+  <FrontDeskNG object at ...>
+  >>> queryAdapter(jack, IDesk, 'ng') #doctest: +ELLIPSIS
+  <FrontDeskNG object at ...>
+
+As you can see, the first argument should be adaptee then, the
+interface which should be provided by component and last the name of
+adapter component.
+
+If you try to lookup the component with an name not used for
+registration but for same adaptee and interface, the lookup will fail.
+Here is how the two methods works in such a case::
+
+  >>> getAdapter(jack, IDesk, 'not-exists') #doctest: +ELLIPSIS
+  Traceback (most recent call last):
+  ...
+  ComponentLookupError: ...
+  >>> reg = queryAdapter(jack,
+  ...           IDesk, 'not-exists') #doctest: +ELLIPSIS
+  >>> reg is None
+  True
+
+As you can see above, `getAdapter` raised a
+`ComponentLookupError` exception, but `queryAdapter`
+returned `None` when lookup failed.
+
+The third argument, the name of registration, is optional.  If the
+third argument is not given it will default to empty string ('').
+Since there is no component registered with an empty string,
+`getAdapter` will raise `ComponentLookupError`.  Similarly
+`queryAdapter` will return `None`, see yourself how it
+works::
+
+  >>> getAdapter(jack, IDesk) #doctest: +ELLIPSIS
+  Traceback (most recent call last):
+  ...
+  ComponentLookupError: ...
+  >>> reg = queryAdapter(jack, IDesk) #doctest: +ELLIPSIS
+  >>> reg is None
+  True
+
+In this section you have learned how to register a simple adapter and
+how to retrieve it from component registry.  These kind of adapters is
+called single adapter, because it adapts only one adaptee.  If an
+adapter adapts more that one adaptee, then it is called multi adapter.
+
+
+Retrieving adapter using interface
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Adapters can be directly retrieved using interfaces, but it will only
+work for non-named single adapters.  The first argument is the adaptee
+and the second argument is a keyword argument.  If adapter lookup
+fails, second argument will be returned.
+
+::
+
+  >>> IDesk(jack, alternate='default-output')
+  'default-output'
+
+  Keyword name can be omitted:
+
+  >>> IDesk(jack, 'default-output')
+  'default-output'
+
+  If second argument is not given, it will raise `TypeError`:
+
+  >>> IDesk(jack) #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
+  Traceback (most recent call last):
+  ...
+  TypeError: ('Could not adapt',
+    <Guest object at ...>,
+    <InterfaceClass __builtin__.IDesk>)
+
+  Here `FrontDeskNG` is registered without name:
+
+  >>> gsm.registerAdapter(FrontDeskNG)
+
+  Now the adapter lookup should succeed:
+
+  >>> IDesk(jack, 'default-output') #doctest: +ELLIPSIS
+  <FrontDeskNG object at ...>
+
+For simple cases, you may use interface to get adapter components.
+
+
+Utility
+-------
+
+Now you know the concept of interface, adapter and component registry.
+Sometimes it would be useful to register an object which is not
+adapting anything.  Database connection, XML parser, object returning
+unique Ids etc. are examples of these kinds of objects.  These kind of
+components provided by the ZCA are called `utility` components.
+
+Utilities are just objects that provide an interface and that are
+looked up by an interface and a name.  This approach creates a global
+registry by which instances can be registered and accessed by
+different parts of your application, with no need to pass the
+instances around as parameters.
+
+You need not to register all component instances like this.  Only
+register components which you want to make replaceable.
+
+
+Simple utility
+~~~~~~~~~~~~~~
+
+A utility can be registered with a name or without a name.  A utility
+registered with a name is called named utility, which you will see in
+the next section.  Before implementing the utility, as usual, define
+its interface.  Here is a `greeter` interface::
+
+  >>> from zope.interface import Interface
+  >>> from zope.interface import implements
+
+  >>> class IGreeter(Interface):
+  ...
+  ...     def greet(name):
+  ...         """Say hello"""
+
+Like an adapter a utility may have more than one implementation.  Here
+is a possible implementation of the above interface::
+
+  >>> class Greeter(object):
+  ...
+  ...     implements(IGreeter)
+  ...
+  ...     def greet(self, name):
+  ...         return "Hello " + name
+
+The actual utility will be an instance of this class.  To use this
+utility, you have to register it, later you can query it using the ZCA
+API.  You can register an instance of this class (`utility`) using
+`registerUtility`::
+
+  >>> from zope.component import getGlobalSiteManager
+  >>> gsm = getGlobalSiteManager()
+
+  >>> greet = Greeter()
+  >>> gsm.registerUtility(greet, IGreeter)
+
+In this example you registered the utility as providing the `IGreeter`
+interface.  You can look the interface up with either `queryUtility`
+or `getUtility`::
+
+  >>> from zope.component import queryUtility
+  >>> from zope.component import getUtility
+
+  >>> queryUtility(IGreeter).greet('Jack')
+  'Hello Jack'
+
+  >>> getUtility(IGreeter).greet('Jack')
+  'Hello Jack'
+
+As you can see, adapters are normally classes, but utilities are
+normally instances of classes.  Only once you are creating the
+instance of a utility class, but adapter instances are dynamically
+created whenever you query for it.
+
+
+Named utility
+~~~~~~~~~~~~~
+
+When registering a utility component, like adapter, you can use a
+name.  As mentioned in the previous section, a utility registered with
+a particular name is called named utility.
+
+This is how you can register the `greeter` utility with a name::
+
+  >>> greet = Greeter()
+  >>> gsm.registerUtility(greet, IGreeter, 'new')
+
+In this example you registered the utility with a name as providing
+the `IGreeter` interface.  You can look up the interface with either
+`queryUtility` or `getUtility`::
+
+  >>> from zope.component import queryUtility
+  >>> from zope.component import getUtility
+
+  >>> queryUtility(IGreeter, 'new').greet('Jill')
+  'Hello Jill'
+
+  >>> getUtility(IGreeter, 'new').greet('Jill')
+  'Hello Jill'
+
+As you can see here, while querying you have to use the `name` as
+second argument.
+
+Calling `getUtility` function without a name (second argument) is
+equivalent to calling with an empty string as the name.  Because, the
+default value for second (keyword) argument is an empty string.
+Then, component lookup mechanism will try to find the component with
+name as empty string, and it will fail.  When component lookup fails
+it will raise `ComponentLookupError` exception.  Remember, it will
+not return some random component registered with some other name.
+The adapter look up functions, `getAdapter` and `queryAdapter` also
+works similarly.

Modified: zope3book/trunk/source/conf.py
===================================================================
--- zope3book/trunk/source/conf.py	2009-02-20 17:55:43 UTC (rev 96846)
+++ zope3book/trunk/source/conf.py	2009-02-20 19:10:14 UTC (rev 96847)
@@ -49,9 +49,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = '3.5'
+version = '3.4'
 # The full version, including alpha/beta/rc tags.
-release = '3.5dev'
+release = '3.4.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
@@ -153,7 +153,7 @@
 #html_file_suffix = ''
 
 # Output file base name for HTML help builder.
-htmlhelp_basename = 'ZopeDevelopersGuidedoc'
+htmlhelp_basename = 'Zope3DevelopersBook'
 
 
 # Options for LaTeX output
@@ -169,7 +169,7 @@
 # (source start file, target name, title, author, document class [howto/manual]).
 latex_documents = [
   ('index', 'Zope3DevelopersBook.tex', ur"Zope 3 Developer's Book",
-   ur'Zope Community', 'manual'),
+   ur'Zope Community', 'manual', 1),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
@@ -188,3 +188,9 @@
 
 # If false, no module index is generated.
 #latex_use_modindex = True
+# Additional stuff for the LaTeX preamble.
+
+latex_elements = {
+    'fontpkg': '\\usepackage{palatino}'
+}
+

Added: zope3book/trunk/source/content-components.rst
===================================================================
--- zope3book/trunk/source/content-components.rst	                        (rev 0)
+++ zope3book/trunk/source/content-components.rst	2009-02-20 19:10:14 UTC (rev 96847)
@@ -0,0 +1,520 @@
+Content Components
+==================
+
+Introduction
+------------
+
+See this example::
+
+  >>> from zope import interface
+
+  >>> class IPerson(interface.Interface):
+  ...     name = interface.Attribute("Name")
+  >>> class Person(object):
+  ...     interface.implements(IPerson)
+  ...     name = None
+  >>> jack = Person()
+  >>> jack.name = "Jack"
+
+Here `jack` is a content component.  So a content component is nothing but an
+object which provides a particular interface.  As said in the previous chapter,
+use ``zope.schema`` to define fields of interface.  The above interface can be
+declared like this::
+
+  >>> from zope import interface
+  >>> from zope import schema
+
+  >>> class IPerson(interface.Interface):
+  ...     name = schema.TextLine(
+  ...         title=u"Name",
+  ...         description=u"Name of person",
+  ...         default=u"",
+  ...         required=True)
+
+If you are developing an enterprise application content will be the most
+important thing you have to organize first.  To learn Zope 3 application
+development with content components, this chapter introduce a simple
+ticket/issue collector application.
+
+First look at the user stories, this book will implement these stories in
+coming chapters.
+
+  1. Individual small ticket collector for each project.  Many collectors can
+     be added to one running zope.
+
+  2. Any number of tickets can be added to one collector.
+
+  3. Each ticket will be added with a description and one initial comment.
+
+  4. Additional comments can be added to tickets.
+
+This chapter starts a simple implementation of ticket collector.
+
+As stated above, our goal is to develop a fully functional, though not
+great-looking, web-based ticket collector application.  The root object will be
+the ``Collector``, which can contain ``Ticket`` objects from various users.
+Since you want to allow people to respond to various tickets, you have to allow
+tickets to contain replies, which are ``Comment`` objects.
+
+That means you have two container-based components: The ``Collector`` contains
+only tickets and can be added to any Folder or container that wishes to be able
+to contain it.  To make the ticket collector more interesting, it also has a
+description, which briefly introduces the subject/theme of the discussions
+hosted.  ``Tickets``, on the other hand should be only contained by ticket
+collector.  They will each have a summary and a description.  And last
+``Comment`` should be only contained by tickets.
+
+This setup should contain all the essential things that you need to make the
+object usable.  Later on you will associate a lot of other meta-data with these
+components to integrate them even better into Zope 3 and add additional
+functionality.
+
+The most convenient place to put your package is ``$HOME/myzope/lib/python``.
+To create that package, add a directory using::
+
+  $ cd $HOME/myzope/lib/python/
+  $ mkdir collector
+
+on GNU/Linux.
+
+To make this directory a package, place an empty __init__.py file in the new
+directory.  In GNU/Linux you can do something like::
+
+  $ echo "# Make it a Python package" >> collector/__init__.py
+
+but you can of course also just use a text editor and save a file of this name.
+Just make sure that there is valid Python code in the file.  The file should at
+least contain some whitespace, since empty files confuse some archive programs.
+
+From now on you are only going to work inside this ``collector`` package, which
+should be located at ``$HOME/myzope/lib/python/collector``.
+
+
+Interfaces
+----------
+
+The very first step of the coding process is always to define your interfaces,
+which represent your external API. You should be aware that software that is
+built on top of your packages expect the interfaces to behave exactly the way
+you specify them. This is often less of an issue for attributes and arguments
+of a method, but often enough developers forget to specify what the expected
+return value of a method or function is or which exceptions it can raise or
+catch.
+
+Interfaces are commonly stored in an ``interfaces`` module or package. Since
+our package is not that big, you are going to use a file-based module; therefore
+start editing a file called ``interfaces.py`` in your favorite editor.
+
+In this initial step of our application, you are only interested in defining one
+interface for the ticket collector itself and one for a single ticket, which
+are listed below (add these to the file ``interfaces.py``)::
+
+  from zope.interface import Interface
+  from zope.schema import Text, TextLine, Field
+
+  from zope.app.container.constraints import containers, contains
+  from zope.app.container.interfaces import IContained, IContainer
+
+  class IComment(Interface):
+      """Comment for Ticket"""
+
+      body = Text(
+          title=u"Additional Comment",
+          description=u"Body of the Comment.",
+          default=u"",
+          required=True)
+
+  class ITicket(IContainer):
+      """A ticket object."""
+
+      summary = TextLine(
+          title=u"Summary",
+          description=u"Short summary",
+          default=u"",
+          required=True)
+    
+      description = Text(
+          title=u"Description",
+          description=u"Full description",
+          default=u"",
+          required=False)
+
+      contains('.IComment')
+
+  class ICollector(IContainer):
+      """Collector the base object. It can only
+      contains ITicket objects."""
+
+      contains('.ITicket')
+    
+      description = Text(
+          title=u"Description",
+          description=u"A description of the collector.",
+          default=u"",
+          required=False)
+
+
+  class ITicketContained(IContained):
+      """Interface that specifies the type of objects that can contain
+      tickets.  So a ticket can only contain in a collector."""
+
+      containers(ICollector)
+
+  class ICommentContained(IContained):
+      """Interface that specifies the type of objects that can contain
+      comments.  So a comment can only contain in a ticket."""
+
+      containers(ITicket)
+
+If you want a hierarchy of comments, the ``IComment`` and ``ICommentContained``
+can be changed like this::
+
+  class IComment(Interface):
+      """Comment for Ticket"""
+
+      body = Text(
+          title=u"Additional Comment",
+          description=u"Body of the Comment.",
+          default=u"",
+          required=True)
+
+      contains('.IComment')
+
+  class ICommentContained(IContained):
+      """Interface that specifies the type of objects that can contain
+      comments.  So a comment can contain in a ticket or a comment itself."""
+
+      containers(ITicket, IComment)
+
+See the ``IComment`` interface calls ``contains`` function with ``.IComment``
+as argument.  And in ``ICommentContained`` interface, ``IComment`` is also
+added.  But for simplicity these interfaces are not used in this chapter.
+
+
+Unit tests
+----------
+
+Unit testing is explained in another chapter_ .  Here you can see some
+boiler-plate code which helps to run the doctest based unittests which you will
+write later.  Since `Collector` and `Ticket` objects are containers, this code
+also run common tests for containers.  By convention write all unit test files
+under `tests` directory.  But doctest files are placed in the package directory
+itself.
+
+.. _chapter: /ZopeGuideUnitTesting
+
+First create ``tests/test_collector.py``::
+
+  import unittest
+  from zope.testing.doctestunit import DocTestSuite
+
+  from zope.app.container.tests.test_icontainer import TestSampleContainer
+
+  from collector.ticketcollector import Collector
+
+
+  class Test(TestSampleContainer):
+
+      def makeTestObject(self):
+          return Collector()
+
+  def test_suite():
+      return unittest.TestSuite((
+          DocTestSuite('collector.ticketcollector'),
+          unittest.makeSuite(Test),
+          ))
+
+  if __name__ == '__main__':
+      unittest.main(defaultTest='test_suite')
+
+
+Then ``tests/test_ticket.py``::
+
+  import unittest
+  from zope.testing.doctestunit import DocTestSuite
+
+  from zope.app.container.tests.test_icontainer import TestSampleContainer
+
+  from collector.ticket import Ticket
+
+
+  class Test(TestSampleContainer):
+
+      def makeTestObject(self):
+          return Ticket()
+
+  def test_suite():
+      return unittest.TestSuite((
+          DocTestSuite('collector.ticket'),
+          unittest.makeSuite(Test),
+          ))
+
+  if __name__ == '__main__':
+      unittest.main(defaultTest='test_suite')
+
+``tests/test_comment.py``::
+
+  import unittest
+  from zope.testing.doctestunit import DocTestSuite
+
+  def test_suite():
+      return unittest.TestSuite((
+          DocTestSuite('collector.comment'),
+          ))
+
+  if __name__ == '__main__':
+      unittest.main(defaultTest='test_suite')
+
+To run the unit test::
+
+  $ cd $HOME/myzope/etc
+  $ ../bin/test -vpu --dir collector
+
+Of course now all tests should fail.  In next section you will write doctests
+along with implemetation.
+
+
+Implementation
+--------------
+
+As you can see in the unit test module, collector is going to be implemented in
+``ticketcollector.py``.  A base class, ``BTreeContainer`` is used to implement
+the container.  This will make the implementation easier.
+
+Here is the ``ticketcollector.py``::
+
+  from zope.interface import implements
+  from zope.app.container.btree import BTreeContainer
+
+  from interfaces import ICollector
+
+  class Collector(BTreeContainer):
+      """A simple implementation of a collector using B-Tree Containers.
+
+      Make sure that the ``Collector`` implements the ``ICollector``
+      interface::
+
+        >>> from zope.interface.verify import verifyClass
+        >>> verifyClass(ICollector, Collector)
+        True
+    
+      Here is an example of changing the description of the collector::
+
+        >>> collector = Collector()
+        >>> collector.description
+        u''
+        >>> collector.description = u'Ticket Collector Description'
+        >>> collector.description
+        u'Ticket Collector Description'
+      """
+
+      implements(ICollector)
+
+      description = u''
+
+
+Similarly ``ticket.py``::
+
+  from zope.interface import implements
+  from zope.interface import classProvides
+  from zope.app.container.btree import BTreeContainer
+  from zope.app.container.contained import Contained
+
+  from interfaces import ITicket, ITicketContained
+
+  class Ticket(BTreeContainer, Contained):
+      """A simple implementation of a ticket using B-Tree Containers.
+
+      Make sure that the ``Ticket`` implements the ``ITicket`` interface::
+
+        >>> from zope.interface.verify import verifyClass
+        >>> verifyClass(ITicket, Ticket)
+        True
+
+      Here is an example of changing the summary and description of the ticket::
+
+        >>> ticket = Ticket()
+        >>> ticket.summary
+        u''
+        >>> ticket.description
+        u''
+        >>> ticket.summary = u'Ticket Summary'
+        >>> ticket.description = u'Ticket Description'
+        >>> ticket.summary
+        u'Ticket Summary'
+        >>> ticket.description
+        u'Ticket Description'
+      """
+
+      implements(ITicket, ITicketContained)
+
+      summary = u''
+      description = u''
+
+Then `comment.py`::
+
+  from zope.interface import implements
+
+  from interfaces import IComment
+  from interfaces import ICommentContained
+  from zope.app.container.contained import Contained
+
+  class Comment(Contained):
+      """A simple implementation of a comment.
+
+      Make sure that the ``Comment`` implements the ``IComment`` interface::
+
+        >>> from zope.interface.verify import verifyClass
+        >>> verifyClass(IComment, Comment)
+        True
+
+      Here is an example of changing the body of the comment::
+
+        >>> comment = Comment()
+        >>> comment.body
+        u''
+        >>> comment.body = u'Comment Body'
+        >>> comment.body
+        u'Comment Body'
+      """
+
+      implements(IComment, ICommentContained)
+
+      body = u""
+
+
+Registration
+------------
+
+You have written interfaces and its implementations, now how to bind this with
+Zope 3 framework.  You can use use Zope Configuration Markup Language (ZCML)
+based configuration file for this.
+
+This is our configure.zcml::
+
+  <configure
+      xmlns="http://namespaces.zope.org/zope"
+      i18n_domain="collector">
+
+    <interface 
+        interface=".interfaces.ICollector" 
+        type="zope.app.content.interfaces.IContentType"
+        /> 
+
+    <class class=".ticketcollector.Collector">
+      <implements
+          interface="zope.annotation.interfaces.IAttributeAnnotatable"
+          />
+      <implements
+          interface="zope.app.container.interfaces.IContentContainer" 
+          />
+      <require
+          permission="zope.ManageContent"
+          set_schema=".interfaces.ICollector"
+          />
+      <require
+          permission="zope.ManageContent"
+          interface=".interfaces.ICollector"
+          />
+    </class>
+
+    <interface 
+        interface=".interfaces.ITicket" 
+        type="zope.app.content.interfaces.IContentType"
+        /> 
+
+    <class class=".ticket.Ticket">
+      <implements
+          interface="zope.annotation.interfaces.IAttributeAnnotatable"
+          />
+      <implements
+          interface="zope.app.container.interfaces.IContentContainer" 
+          />
+      <require
+          permission="zope.ManageContent"
+          set_schema=".interfaces.ITicket"
+          />
+      <require
+          permission="zope.ManageContent"
+          interface=".interfaces.ITicket"
+          />
+    </class>
+
+    <interface 
+        interface=".interfaces.IComment" 
+        type="zope.app.content.interfaces.IContentType"
+        /> 
+
+    <class class=".comment.Comment">
+      <implements
+          interface="zope.annotation.interfaces.IAttributeAnnotatable"
+          />
+      <require
+          permission="zope.ManageContent"
+          set_schema=".interfaces.IComment"
+          />
+      <require
+          permission="zope.ManageContent"
+          interface=".interfaces.IComment"
+          />
+    </class>
+
+    <include package=".browser" />
+
+  </configure>
+
+
+Running application
+-------------------
+
+Before running the applcation create one view for ``Collector``.
+
+Create a `browser` directory and under that, a new `configure.zcml`
+file::
+
+  <configure
+      xmlns="http://namespaces.zope.org/browser">
+
+    <addMenuItem
+        class="collector.ticketcollector.Collector"
+        title="Collector"
+        description="A Collector"
+        permission="zope.ManageContent"
+        />
+
+  </configure>
+
+The ``class`` attribute specifies the module path for the class, a leading dot
+means to make the import relative to the package containing the ZCML file.
+Therefore in this case Zope will import the collector.ticketcollector module,
+then import "Collector" from that module.
+
+The ``title`` attribute provides the title to display in the add menu.
+
+The ``permission`` attribute is used to describe what permission is required
+for a person to be able to add one of these objects.  The
+``zope.ManageContent`` permission means that the user can add, remove, and
+modify content (the "admin" user you created while making the instance is one
+such user).
+
+You have to tell Zope to read our ZCML file, and the easiest way to do that is
+to put a "slug" in the $HOME/myzope/etc/package-includes/ directory.  A
+``slug`` is a ZCML file that just includes another file.  Here's what our slug
+should look like (save it as "collector-configure.zcml")::
+
+  <include package="collector" />
+
+Now if you start Zope back up, you can go to the ZMI and add our content type by
+clicking on "Add Collector" and entering a name for our object; name it
+"MyCollector".
+
+Now restart Zope and visit http://localhost:8080 .  You can add collector from
+menu.
+
+
+Views
+-----
+
+
+Functional testing
+------------------

Added: zope3book/trunk/source/development-tools.rst
===================================================================
--- zope3book/trunk/source/development-tools.rst	                        (rev 0)
+++ zope3book/trunk/source/development-tools.rst	2009-02-20 19:10:14 UTC (rev 96847)
@@ -0,0 +1,194 @@
+Development Tools
+=================
+
+Before going to the details about how to develop a web application
+using Python and Zope components, we should familiarize some
+essential tools like Python eggs, setuptools and buildouts.  If you
+are already familiar with these you may skip this chapter.
+
+
+Eggs
+----
+
+Eggs are Python's new distribution format managed using `setuptool`
+package http://peak.telecommunity.com/DevCenter/PythonEggs .
+
+To install an egg, you can use easy_install program
+http://peak.telecommunity.com/DevCenter/EasyInstall .
+
+An easy way to automate the installtion would be to use
+easy_setup.py program.
+
+::
+
+  $ wget -c http://peak.telecommunity.com/dist/ez_setup.py
+  $ python easy_setup.py
+
+
+Buildout
+--------
+
+The Buildout project provides support for creating applications,
+especially Python applications.  It provides tools for assembling
+applications from multiple parts, Python or otherwise.  An
+application may actually contain multiple programs, processes, and
+configuration settings.
+
+The word `buildout` refers to a description of a set of parts and the
+software to create and assemble them.  It is often used informally to
+refer to an installed system based on a buildout definition.  For
+example, if we are creating an application named `Foo``, then `the
+Foo buildout` is the collection of configuration and
+application-specific software that allows an instance of the
+application to be created.  We may refer to such an instance of the
+application informally as `a Foo buildout`.
+
+Buildout provides support for creating, assembling and deploying
+applications, especially Python applications.  You can build
+applications using Buildout recipes.  Recipes are Python programs
+which follows a pattern to build various parts of an application.
+For example, a recipe will install Python eggs and another one will
+install test runner etc.  Applications can be assembled from multiple
+parts with different configurations.  A part can be a Python egg or
+any other program.  We have already seen how to use buildout to setup
+a Zope~3 application in the getting started chapter.
+
+Buildout recipes
+----------------
+
+Buildout recipes are distributed in egg formats.  Some examples of
+recipes are:
+
+* zc.recipe.egg -- The egg recipe installes one or more eggs, with
+  their dependencies. It installs their console-script entry points
+  with the needed eggs included in their paths.
+
+* zc.recipe.testrunner -- The testrunner recipe creates a test runner
+  script for one or more eggs.
+
+* zc.recipe.zope3recipes -- Recipes for creating Zope 3 instances
+  with distinguishing features:
+
+  - Don't use a skeleton
+
+  - Separates application and instance definition
+
+  - Don't support package-includes
+
+
+* zc.recipe.filestorage -- The filestorage recipe sets up a ZODB file
+  storage for use in a Zope 3 instance creayed by the `zope3recipes`
+  recipe.
+
+
+Using a recipe
+~~~~~~~~~~~~~~
+
+The procedure for using a recipe is common for almost all recipes.
+You can create buildouts with parts controlled recipes.  Suppose you
+want to experiment with one package, say, `zope.component`, you can
+use `zc.recipe.egg` for installing it in buildout.  The
+`zc.recipe.egg` will also provide an interpreter with the egg
+installed in the path.  First you can create a directory and
+initialize Buildout:
+
+::
+
+  $ mkdir explore-zope.component
+  $ cd explore-zope.component
+  $ echo "#Buildout configuration" > buildout.cfg
+  $ svn co svn://svn.zope.org/repos/main/zc.buildout/trunk/bootstrap
+  $ ~/usr/bin/python2.4 bootstrap/bootstrap.py
+
+Now modify the buildout.cfg like this::
+
+  [buildout]
+  parts = py
+
+  [py]
+  recipe = zc.recipe.egg
+  interpreter = mypython
+  eggs = zope.component
+
+Now run `buildout` script inside `bin` directory.  This will download
+zope.component and its dependency eggs and install it.  Now you can
+access the interpreter created by the Buildout recipe like this::
+
+  $ ./bin/buildout
+  $ ./bin/mypython
+  >>> import zope.component
+
+
+Developing a package
+--------------------
+
+The initial steps are not different from the above exmaple::
+
+  $ mkdir hello
+  $ cd hello
+  $ echo "#Buildout configuration" > buildout.cfg
+  $ svn co svn://svn.zope.org/repos/main/zc.buildout/trunk/bootstrap
+  $ ~/usr/bin/python2.4 bootstrap/bootstrap.py
+
+Our application is a simple hello world package.  First we will
+create an `src` directory to place our package.  Inside the `src`
+directory, you can create the `hello` Python package.  You can create
+the `src` and the `hello` package like this::
+
+  $ mkdir src
+  $ mkdir src/hello
+  $ echo "#Python package" > src/hello/__init__.py
+
+
+Now create a file named `say.py` inside the `hello` package with this
+code::
+
+  def say_hello():
+      print "Hello"
+
+To start building our package you have to create a `setup.py` file.
+The `setup.py` should have the minimum details as given below::
+
+  from setuptools import setup, find_packages
+
+  setup(
+    name='hello',
+    version='0.1',
+
+    packages=find_packages('src'),
+    package_dir={'': 'src'},
+
+    install_requires=['setuptools',
+                      ],
+    entry_points = {'console_scripts':
+                    ['print_hello = hello.say:say_hello']},
+    include_package_data=True,
+    zip_safe=False,
+    )
+
+Modify `buildout.cfg` as given below::
+
+  [buildout]
+  develop = .
+  parts = py
+
+  [py]
+  recipe = zc.recipe.egg
+  scripts = print_hello
+  eggs = hello
+
+Now run `buildout` script inside `bin` directory.  Now you
+can run the `print_hello` script.
+
+::
+
+  $ ./bin/buildout
+  $ ./bin/print_hello
+  Hello
+
+
+Summary
+-------
+
+This chapter provided a brief introduction to eggs.  Later we found
+how to use buildout tool for developing application.

Copied: zope3book/trunk/source/getting-started.rst (from rev 96811, zope3book/trunk/source/InstallingZope3.rst)
===================================================================
--- zope3book/trunk/source/getting-started.rst	                        (rev 0)
+++ zope3book/trunk/source/getting-started.rst	2009-02-20 19:10:14 UTC (rev 96847)
@@ -0,0 +1,431 @@
+Getting Started
+===============
+
+Introduction
+------------
+
+This chapter cover the details of setting up an isolated working
+environment for web application development using Python and Zope
+components.  As the first step, you will be required to install
+Python.  Then, a basic understanding of Buildout, the build system
+used to set up development sandbox is required.  More details about
+Buildout is given in the next chapter.  Buildout will take care of
+download and installion of all the dependency packages.  To create a
+project code base, you need to provide the minimal meta-data required
+for your project like name, version etc.  These details can be given
+in `setup.py` and other configuration details in `buildout.cfg`.
+
+
+Python installation
+-------------------
+
+The Zope community has always recommended using a custom built Python
+for development and deployment.  Both Python 2.4 and 2.5 should work
+for Zope 3.4 KGS packages.  As of now, the author reccomend using
+Python 2.5 for any new project.
+
+
+GNU/Linux
+~~~~~~~~~
+
+To install Python, you will be required to install gcc, g++ and other
+development tools in your system.  A typical installation of Python can
+be done like this:
+
+::
+
+  $ wget -c http://www.python.org/ftp/python/2.4.5/Python-2.4.5.tar.bz2
+  $ tar jxvf Python-2.4.5.tar.bz2
+  $ cd Python-2.4.5
+  $ ./configure --prefix=/home/guest/usr
+  $ make
+  $ make install
+
+As given above, you can provide an option, ``--prefix`` to install
+Python in a particular location.  The above steps install Python
+inside ``/home/guest/usr`` directory.
+
+After installation, you can invoke the Python interpreter like this::
+
+  $ ~/usr/bin/python2.4
+  >>> print "Hello, world!"
+  Hello, world!
+
+.. note::
+
+  If you are not getting old statements in Python interactive prompt
+  when using up-arrow key, try installing libreadline development
+  libraries (Hint: apt-cache search libreadline).  After installing
+  this library, you should install Python again.  You also will be
+  required to install zlib (Hint: apt-cache search zlib compression
+  library) to properly install Zope 3.
+
+
+MS Windows
+~~~~~~~~~~
+
+Python provide binaries for MS Windows.  You can use the MSI
+installer package from python.org
+
+
+Buildout
+--------
+
+Introduction
+~~~~~~~~~~~~
+
+We are going to use a build tool called Buildout for developing Zope
+3 applications from multiple parts.  Buildout will give you an
+isolated working environment for developing applications.  The
+Buildout package, named `zc.buildout` is available for download from
+PyPI.  This section briefly goes through the usage of Buildout for
+developing applications.
+
+Buildout has a `boostrap.py` script for initializing a buildout based
+project for development or deployment.  It will download and install
+`zc.buildout`, `setuptools` and other dependency modules in a
+specified directory.  Once bootstrapped it will create a buildout
+executable script inside `bin` directory at the top of your project
+source.  The default configuration for each project is `buildout.cfg`
+file at the top of your project source.  Whenever you run the
+buildout command it will look into the default configuration file and
+will do actions based on it.  Normally, the configuration file and
+boostrap script will be bundled with the project source itself.
+Other than the default configuration file along with the project
+source, you may also create a system wide default configuration file
+at `~/.buildout/default.cfg` .
+
+Buildout creator Jim Fulton recommend a custom built clean Python
+installation, i.e., there should not be any Python modules installed
+in your site-packages (ideally, a fresh Python installation).  When you
+boostrap your project using Buildout's boostrap.py script, it will
+download and install all necessary packages in a specified directory.
+So, for an ideal project you only required a custom built clean Python
+and the project source with proper Buildout configuration and
+bootstrap script along with the source package.
+
+
+Buildout configuration
+~~~~~~~~~~~~~~~~~~~~~~
+
+These days, most of the Python packages are available in egg_ format.
+Buildout will download and install the eggs in a specified directory
+and the location can be changed from the configuration file.  It is
+better to give a system-wide location for eggs directory.  And this
+configuration can be added to your system-wide configuration file.
+The default configuration file for Buildout is
+`~/.buildout/default.cfg` .  We are going to use `eggs` directory
+inside your home directory to keep all eggs, so first create those
+directories and global configuration file::
+
+  $ cd $HOME
+  $ mkdir .buildout
+  $ mkdir eggs
+  $ touch .buildout/default.cfg
+
+You can add the following to your global configuration file
+(`~/.buildout/default.cfg`)::
+
+  [buildout]
+  newest = false
+  eggs-directory = /home/guest/eggs
+  find-links = http://download.zope.org/ppix
+
+The `eggs-directory` is where Buildout stores the eggs that are
+downloaded.  The last option, `find-links` points to a reliable
+mirror of the Python Package Index (PyPI).  The default
+configurations given above will be available to all buildouts in your
+system.
+
+.. _egg: http://peak.telecommunity.com/DevCenter/PythonEggs
+
+
+Setting up development sandbox
+------------------------------
+
+To demonstrate the concepts, tools and techniques, we are going to
+develop a ticket collector application.  To begin the work, first
+create a directory for the project.  After creating the directory,
+create a configuration file, `buildout.cfg` as given below.  To
+bootstrap this application checkout bootstrap.py and run it using a
+clean Python.
+
+::
+
+  $ mkdir ticketcollector
+  $ cd ticketcollector
+  $ echo "#Buildout configuration" > buildout.cfg
+  $ svn co svn://svn.zope.org/repos/main/zc.buildout/trunk/bootstrap
+  $ ~/usr/bin/python2.4 bootstrap/bootstrap.py
+
+You can see a `buildout` script created inside `bin` directory.  Now
+onwards, run this `buildout` script whenever you are changing
+Buildout configuration.
+
+.. note::
+
+  You can save `bootstrap.py` in a local repository.  If you are
+  using svn for managing repository, create an `svn:external` to the
+  svn URL given above.
+
+Our application is basically a Python package.  First, we will create
+an `src` directory to place our package.  Inside the `src` directory,
+you can create `ticketcollector` Python package.  You can create the
+`src` and the `ticketcollector` package like this::
+
+  $ mkdir src
+  $ mkdir src/ticketcollector
+  $ echo "#Python package" > src/ticketcollector/__init__.py
+
+To start building our package you have to create a `setup.py` file.
+The `setup.py` should have the minimum details as given below::
+
+  from setuptools import setup, find_packages
+
+  setup(
+      name='ticketcollector',
+      version='0.1',
+
+      packages=find_packages('src'),
+      package_dir={'': 'src'},
+
+      install_requires=['setuptools',
+                        'zope.app.zcmlfiles',
+                        'zope.app.twisted',
+                        'zope.app.securitypolicy',
+                        ],
+      include_package_data=True,
+      zip_safe=False,
+      )
+
+We have included the bare minimum packages required for installation
+in `install_requires` argument: `zope.app.zcmlfiles`,
+`zope.app.twisted` , `zope.app.securitypolicy` and `setuptools`.
+
+To make this package buildout aware, we have to modify the
+`buildout.cfg` as given below::
+
+  [buildout]
+  develop = .
+  parts = py
+  extends = http://download.zope.org/zope3.4/3.4.0/versions.cfg
+  versions = versions
+
+  [py]
+  recipe = zc.recipe.egg
+  eggs = ticketcollector
+  interpreter = python
+
+Now run the `buildout` script inside `bin` directory.  This will download
+all necessary eggs and install it.
+
+::
+
+  $ ./bin/buildout
+
+As you can see above, installing Zope is nothing but just setting up
+a buildout with `setup.py` with proper packages given as
+`install_requires` in it.
+
+.. note::
+
+  Unless you specify a parts section which use `ticketcollector` in some
+  way, Buildout will not download dependency packages.  In the above
+  example, we created a `[py]` section with `zc.recipe.egg` recipe.
+
+
+A simple application
+--------------------
+
+
+Configuring application
+~~~~~~~~~~~~~~~~~~~~~~~
+
+We are going to continue the Ticket Collector application in this
+section.  In the last section when you run `./bin/buildout` command
+all necessary Zope 3 packages required for running our application is
+downloaded inside `~/eggs` directory.  Now to run the bare minimum
+Zope 3, we have to create Zope Configuration Markup Language (ZCML)
+file and extend the `buildout.cfg` with appropriate Buildout recipes.
+We are going to use `zc.zope3recipes:app`, `zc.zope3recipes:instance`
+and `zc.recipe.filestorage` recipes for setting up our application.
+Here is our modified buildout.cfg (inside the ticketcollector project
+directory)::
+
+  [buildout]
+  develop = .
+  parts = ticketcollectorapp instance
+
+  [zope3]
+  location =
+
+  [ticketcollectorapp]
+  recipe = zc.zope3recipes:app
+  site.zcml =
+    <include
+      package="ticketcollector"
+      file="application.zcml"
+      />
+  eggs = ticketcollector
+
+  [instance]
+  recipe = zc.zope3recipes:instance
+  application = ticketcollectorapp
+  zope.conf = ${database:zconfig}
+
+  [database]
+  recipe = zc.recipe.filestorage
+
+Then we will create `application.zcml` inside `src/ticketcollector`
+directory with the following text.  Consider it as boiler plate code
+now, we will explain this in detail later::
+
+  <configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    >
+
+    <include package="zope.securitypolicy"
+      file="meta.zcml"
+      />
+
+    <include package="zope.app.zcmlfiles" />
+    <include package="zope.app.authentication" />
+    <include package="zope.app.securitypolicy" />
+    <include package="zope.app.twisted" />
+
+    <securityPolicy
+      component="zope.securitypolicy.zopepolicy.ZopeSecurityPolicy"
+      />
+
+    <role id="zope.Anonymous" title="Everybody"
+      description="All users have this role implicitly"
+      />
+
+    <role id="zope.Manager" title="Site Manager" />
+
+    <role id="zope.Member" title="Site Member" />
+
+    <grant permission="zope.View"
+      role="zope.Anonymous"
+      />
+
+    <grant permission="zope.app.dublincore.view"
+      role="zope.Anonymous"
+      />
+
+    <grantAll role="zope.Manager" />
+
+    <unauthenticatedPrincipal
+      id="zope.anybody"
+      title="Unauthenticated User"
+      />
+
+    <unauthenticatedGroup
+      id="zope.Anybody"
+      title="Unauthenticated Users"
+      />
+
+    <authenticatedGroup
+      id="zope.Authenticated"
+      title="Authenticated Users"
+      />
+
+    <everybodyGroup
+      id="zope.Everybody"
+      title="All Users"
+      />
+
+    <principal
+      id="zope.manager"
+      title="Manager"
+      login="admin"
+      password_manager="Plain Text"
+      password="admin"
+      />
+
+    <grant
+      role="zope.Manager"
+      principal="zope.manager"
+      />
+
+  </configure>
+
+
+Running application
+~~~~~~~~~~~~~~~~~~~
+
+Now you can run the application by executing `./bin/buildout` command
+followed by `./bin/instance` command.
+
+::
+
+  $ ./bin/buildout
+  $ ./bin/instance fg
+
+
+Using ZMI
+~~~~~~~~~
+
+After running your instance, If you open a web browser and go to
+`http://localhost:8080 <http://localhost:8080>`_ you'll see the ZMI
+(Zope Management Interface ).
+
+Go ahead and click the `Login` link at the upper right corner.  Enter
+the user name and password as admin, which is given in
+`applications.zcml`.  Now click on `[top]` under Navigation on the
+right.  Play around with adding some content objects (the Zope 3 name
+for instances that are visible in the ZMI).  Note how content objects
+can be arranged in a hierarchy by adding folders which are special
+content objects that can hold other content objects.
+
+There is nothing special about the ZMI, it is just the default skin
+for Zope 3.  You can modify it to your liking, or replace it
+entirely.
+
+When you're done exploring with the ZMI, go back to the window where
+you typed `./bin/instance fg` and press Control-C to stop Zope 3.
+
+
+Hello world
+~~~~~~~~~~~
+
+Now you can begin your development inside `src/ticketcollector`
+directory.  Create a `browser.py` with following content::
+
+  from zope.publisher.browser import BrowserView
+
+  class HelloView(BrowserView):
+
+      def __call__(self):
+          return """
+          <html>
+          <head>
+            <title>Hello World</title>
+          </head>
+          <body>
+            Hello World
+          </body>
+          </html>
+          """
+
+Now append the following text just above the last line of
+application.zcml::
+
+  <browser:page
+    for="*"
+    name="hello"
+    permission="zope.Public"
+    class="ticketcollector.browser.HelloView"
+    />
+
+After restarting Zope, open `http://localhost:8080/hello
+<http://localhost:8080/hello>`_, you can see that it displays `Hello
+World!`.
+
+
+Conclusion
+----------
+
+Setting up a Zope 3 project sandbox is nothing but creating a proper
+Buildout configuration.


Property changes on: zope3book/trunk/source/getting-started.rst
___________________________________________________________________
Added: svn:mergeinfo
   + 

Modified: zope3book/trunk/source/index.rst
===================================================================
--- zope3book/trunk/source/index.rst	2009-02-20 17:55:43 UTC (rev 96846)
+++ zope3book/trunk/source/index.rst	2009-02-20 19:10:14 UTC (rev 96847)
@@ -1,16 +1,25 @@
-#######################
+.. _contents:
+
 Zope 3 Developer's Book
-#######################
+=======================
 
 .. toctree::
    :maxdepth: 2
 
-   Preface.rst
-   InstallingZope3.rst
+   introduction
+   getting-started
+   development-tools
+   interfaces
+   component-architecture
+   testing
+   browser-resouces
+   browser-pages
+   content-components
+   skinning
 
-##################
+
 Indices and tables
-##################
+==================
 
 * :ref:`genindex`
 * :ref:`modindex`

Added: zope3book/trunk/source/interfaces.rst
===================================================================
--- zope3book/trunk/source/interfaces.rst	                        (rev 0)
+++ zope3book/trunk/source/interfaces.rst	2009-02-20 19:10:14 UTC (rev 96847)
@@ -0,0 +1,326 @@
+Interfaces
+==========
+
+
+Introduction
+------------
+
+Interfaces are objects that specify (document) the external behavior
+of objects that "provide" them.  An interface specifies behavior
+through:
+
+* Informal documentation in a doc string
+
+* Attribute definitions
+
+* Invariants, which are conditions that must hold for objects that
+  provide the interface
+
+Some of the motivations for using interfaces are:
+
+* Avoid monolithic design by developing small, exchangeable pieces
+
+* Model external responsibility, functionality, and behavior
+
+* Establish contracts between pieces of functionality
+
+* Document the API
+
+The classic software engineering book `Design Patterns`_ by the Gang
+of Four recommends: "Program to an interface, not an implementation".
+Defining a formal interface is helpful in understanding a system.
+Moreover, interfaces bring you all the benefits of Zope Component
+Architecture which we are going to learn in next chapter.
+
+In some modern programming languages: Java, C#, VB.NET etc,
+interfaces are an explicit aspect of the language.  Since Python
+lacks interfaces, Zope implements them as a meta-class to inherit
+from.
+
+.. _Design Patterns: http://en.wikipedia.org/wiki/Design_Patterns
+
+
+Types of contract
+-----------------
+
+:"I can do X": Describing the ability to do something is the classical
+  definition of an API.  Those abilities are defined and implemented as
+  methods.
+
+
+:"I have X": This statement declares the availability of data, which
+  is classically associated with schemas.  The data is stored in
+  attributes and properties.
+
+
+:"You can do X with me": Here we describe the behavior of an object.
+  Classically there is no analog.  However, MIME-types are great example
+  of behavior declaration.  This is implemented using empty "marker
+  interfaces" as they describe implicit behavior.
+
+
+The distinction between those three types of contracts was first
+pointed out in this form by Philipp von Weitershausen.
+
+Understanding those distinctions is very important, since other
+programming languages do not necessarily use all three of these
+notions.  In fact, often only the first one is used.
+
+
+Defining interfaces
+-------------------
+
+* Python has no concept of interfaces
+
+* Not a problem
+
+* Interfaces are just objects
+
+* "Abuse" the class statement to create an interface
+
+* Syntax proposed in PEP 245
+
+Jim Fulton does not see this as a problem, since it makes interfaces
+first class citizens.  In Java, for example, interfaces are special
+types of objects that can only serve as interfaces in their intended,
+limited scope.
+
+An interface from the zope.interface package, on the other hand,
+defines the interface by implementing a meta-class, a core concept of
+Python.  Thus, interfaces are merely using an existing Python
+pattern.
+
+
+An example
+----------
+
+Here is a classic hello world style example::
+
+  >>> class Host(object):
+  ...
+  ...     def goodmorning(self, name):
+  ...         """Say good morning to guests"""
+  ...
+  ...         return "Good morning, %s!" % name
+
+
+In the above class, you defined a goodmorning method.  If you call
+the goodmorning method from an object created using this class, it
+will return Good morning, ...!
+
+::
+
+  >>> host = Host()
+  >>> host.goodmorning('Jack')
+  'Good morning, Jack!'
+
+
+Here host is the actual object your code uses.  If you want to
+examine implementation details you need to access the class Host,
+either via the source code or an API_ documentation tool.
+
+Now we will begin to use the Zope interfaces.  For the class given
+above you can specify the interface like this::
+
+  >>> from zope.interface import Interface
+
+  >>> class IHost(Interface):
+  ...
+  ...     def goodmorning(guest):
+  ...         """Say good morning to guest"""
+
+
+As you can see, the interface inherits from zope.interface.Interface.
+This use (abuse?) of Python's class statement is how Zope defines an
+interface.  The I prefix for the interface name is a useful
+convention.
+
+.. _API: http://en.wikipedia.org/wiki/Application_programming_interface
+
+
+Declaring interfaces
+--------------------
+
+You have already seen how to declare an interface using
+`zope.interface` in previous section.  This section will explain the
+concepts in detail.
+
+Consider this example interface::
+
+  >>> from zope.interface import Interface
+  >>> from zope.interface import Attribute
+
+  >>> class IHost(Interface):
+  ...     """A host object"""
+  ...
+  ...     name = Attribute("""Name of host""")
+  ...
+  ...     def goodmorning(guest):
+  ...         """Say good morning to guest"""
+
+
+The interface, `IHost` has two attributes, name and goodmorning.
+Recall that, at least in Python, methods are also attributes of
+classes.  The name attribute is defined using
+zope.interface.Attribute class.  When you add the attribute name to
+the IHost interface, you don't set an initial value.  The purpose of
+defining the attribute name here is merely to indicate that any
+implementation of this interface will feature an attribute named
+name.  In this case, you don't even say what type of attribute it has
+to be!.  You can pass a documentation string as a first argument to
+Attribute.
+
+The other attribute, goodmorning is a method defined using a function
+definition.  Note that self is not required in interfaces, because
+self is an implementation detail of class.  For example, a module can
+implement this interface.  If a module implement this interface,
+there will be a name attribute and goodmorning function defined.  And
+the goodmorning function will accept one argument.
+
+Now you will see how to connect interface-class-object.  So object is
+the real living thing, objects are instances of classes.  And
+interface is the actual definition of the object, so classes are just
+the implementation details.  This is why you should program to an
+interface and not to an implementation.
+
+Now you should familiarize two more terms to understand other
+concepts.  First one is provide and the other one is implement.
+Object provides interfaces and classes implement interfaces.  In
+other words, objects provide interfaces that their classes implement.
+In the above example host (object) provides IHost (interface) and
+Host (class) implement IHost (interface).  One object can provide
+more than one interface also one class can implement more than one
+interface.  Objects can also provide interfaces directly, in addition
+to what their classes implement.
+
+.. note::
+
+  Classes are the implementation details of objects.  In Python,
+  classes are callable objects, so why other callable objects can't
+  implement an interface.  Yes, it is possible.  For any callable
+  object you can declare that it produces objects that provide some
+  interfaces by saying that the callable object implements the
+  interfaces.  The callable objects are generally called as
+  factories.  Since functions are callable objects, a function can be
+  an implementer of an interface.
+
+
+Implementing interfaces
+-----------------------
+
+To declare a class implements a particular interface, use the
+function `zope.interface.implements` in the class statement.
+
+Consider this example, here `Host` implements `IHost`::
+
+  >>> from zope.interface import implements
+
+  >>> class Host(object):
+  ...
+  ...     implements(IHost)
+  ...
+  ...     name = u''
+  ...
+  ...     def goodmorning(self, guest):
+  ...         """Say good morning to guest"""
+  ...
+  ...         return "Good morning, %s!" % guest
+
+
+.. note::
+
+  If you wonder how implements function works, refer the blog post by
+  James Henstridge (`http://blogs.gnome.org/jamesh/2005/09/08
+  /python-class-advisors/ <http://blogs.gnome.org/jamesh/2005/09/08
+  /python-class-advisors/>`__) . In the adapter section, you will see
+  an adapts function, it is also working similarly.
+
+
+Since Host implements IHost, instances of Host provides IHost.  There
+are some utility methods to introspect the declarations.  The
+declaration can write outside the class also.  If you don't write
+interface.implements(IHost) in the above example, then after defining
+the class statement, you can write like this::
+
+  >>> from zope.interface import classImplements
+  >>> classImplements(Host, IHost)
+
+
+Marker interfaces
+-----------------
+
+An interface can be used to declare that a particular object belongs
+to a special type.  An interface without any attribute or method is
+called marker interface.
+
+Here is a marker interface::
+
+  >>> from zope.interface import Interface
+
+  >>> class ISpecialGuest(Interface):
+  ...     """A special guest"""
+
+
+This interface can be used to declare an object is a special guest.
+
+
+Invariants
+----------
+
+Sometimes you will be required to use some rule for your component
+which involve one or more normal attributes.  These kind of rule is
+called `invariants`.  You can use `zope.interface.invariant` for
+setting `invariants` for your objects in their interface.
+
+Consider a simple example, there is a `person` object.  A person
+object has `name`, `email` and `phone` attributes.  How do you
+implement a validation rule that says either email or phone have to
+exist, but not necessarily both.
+
+First you have to make a callable object, either a simple function or
+callable instance of a class like this::
+
+  >>> def contacts_invariant(obj):
+  ...
+  ...     if not (obj.email or obj.phone):
+  ...         raise Exception(
+  ...             "At least one contact info is required")
+
+Then define the `person` object's interface like this.  Use the
+`zope.interface.invariant` function to set the invariant::
+
+  >>> from zope.interface import Interface
+  >>> from zope.interface import Attribute
+  >>> from zope.interface import invariant
+
+  >>> class IPerson(Interface):
+  ...
+  ...     name = Attribute("Name")
+  ...     email = Attribute("Email Address")
+  ...     phone = Attribute("Phone Number")
+  ...
+  ...     invariant(contacts_invariant)
+
+Now use `validateInvariants` method of the interface to validate::
+
+  >>> from zope.interface import implements
+
+  >>> class Person(object):
+  ...     implements(IPerson)
+  ...
+  ...     name = None
+  ...     email = None
+  ...     phone = None
+
+  >>> jack = Person()
+  >>> jack.email = u"jack at some.address.com"
+  >>> IPerson.validateInvariants(jack)
+  >>> jill = Person()
+  >>> IPerson.validateInvariants(jill)
+  Traceback (most recent call last):
+  ...
+  Exception: At least one contact info is required
+
+As you can see `jack` object validated without raising any exception.
+But `jill` object didn't validated the invariant constraint, so it
+raised exception.

Added: zope3book/trunk/source/introduction.rst
===================================================================
--- zope3book/trunk/source/introduction.rst	                        (rev 0)
+++ zope3book/trunk/source/introduction.rst	2009-02-20 19:10:14 UTC (rev 96847)
@@ -0,0 +1,178 @@
+Introduction
+============
+
+
+Overview
+--------
+
+This book is about `Zope 3`_, a Python_ framework for web application
+development.  Zope 3 was developed by the Zope_ community with the
+leadership of Jim Fulton, the creator of original Zope.  Zope 3
+consists of a number of small frameworks and libraries written in
+Python programming language and it is usable in pieces or in whole.
+These frameworks and libraries can be put together to build any kind
+of web application.  Most of of the Zope 3 packages are built on top
+of a `component architecture`_ which helps to separate presentation
+code from the problem domain code and to create reusable components
+(zope.component).
+
+The goal for this book project is to create a complete, free,
+open-content, well-organized book for Zope 3.  The target audience of
+this book are Python programmers looking for developing web
+applications.  However, the book doesn't assume you are familiar with
+any other web framework.  This book will require prior knowledge
+Python programming language and at least some exposure to the basics
+of HTML, CSS and JavaScript.
+
+Zope 3 has an object publisher (zope.publisher), web server
+(zope.server), transactional object database (ZODB), XML based
+configuration language for registering components
+(zope.configuration), flexible security architecture with pluggable
+security policies (zope.security), unit and functional testing
+frameworks (zope.testing , zope.testbrowser), XHTML-compliant
+templating language (zope.pagetemplate), schema engine and automatic
+form generation machinery (zope.schema , z3c.form) and many more core
+and third-party packages.
+
+Originally, the term ZOPE was used as an acronym for Z Object
+Publishing Environment (the Z doesn't really mean anything in
+particular).  However, now-a-days ZOPE is simply written as Zope .
+
+Zope 3 is a ZPL (BSD like, GPL compatible license) licensed free/open
+source software.  It was developed by the Zope community with the
+leadership of Jim Fulton.  A brief history is given in the next
+section.
+
+.. _Zope 3: http://en.wikipedia.org/wiki/Zope_3
+.. _Python: http://en.wikipedia.org/wiki/Python_Programming
+.. _Zope: http://en.wikipedia.org/wiki/Zope
+.. _component architecture: http://wiki.zope.org/zope3/ComponentArchitecture
+.. _Buildout: http://pypi.python.org/pypi/zc.buildout
+
+
+Scope of the book
+-----------------
+
+The intension of this book is not to cover how to use Zope 3 packages
+independently or with other Python applications/frameworks.  Rather,
+this book focus on developing web applications using Zope 3 packages.
+More specifically, this book is not going to cover using Zope 3
+technology in Zope 2, Plone, Grok or any other Python
+application/framework.  WSGI is also not a current focus of this
+book.  This book is not going to cover using `zopeproject` to
+bootstrap application (it's very easy, look at the PyPI page for
+zopeproject).  This book use Buildout for setting up an isolated
+development environment for building applications.  Setuptools and
+vitualenv are also covered.
+
+
+Audience
+--------
+
+The target audience of this book are Python programmers looking for
+developing web applications.  However, the book doesn't assume you are
+familiar with any other web framework.
+
+
+Prerequisites
+-------------
+
+This book will require prior knowledge Python programming language and
+at least some exposure to the basics of HTML, CSS and JavaScript.
+
+
+Brief history
+-------------
+
+The beginning of Zope's story goes something like this, in 1996, Jim
+Fulton (CTO of Zope Corporation) was drafted to teach a class on
+common gateway interface (CGI) programming, despite not knowing very
+much about the subject.  CGI programming is a commonly-used web
+development model that allows developers to construct dynamic
+websites.  On his way to the class, Jim studied all the existing
+documentation on CGI.  On the way back, Jim considered what he didn't
+like about traditional, CGI-based programming environments.  From these
+initial musings, the core of Zope was written while flying back from
+the CGI class.
+
+Zope Corporation (then known as Digital Creations) went on to release
+three open-source software packages to support web publishing: Bobo,
+Document Template, and BoboPOS.  These packages were written in a
+language called Python, and provided a web publishing facility, text
+templating, and an object database, respectively.  Digital Creations
+developed a commercial application server based on their three
+opensource components.  This product was called Principia.  In November
+of 1998, investor Hadar Pedhazur convinced Digital Creations to open
+source Principia.  These packages evolved into what are now the core
+components of Zope 2.
+
+In 2001, the Zope community began working on a component architecture
+for Zope, but after several years they ended up with something much
+more: Zope 3.  While Zope 2 was powerful and popular, Zope 3 was
+designed to bring web application development to the next level.  This
+book is about this Zope 3, which is not really a new version of Zope
+2.
+
+Most recently, in 2007 the Zope community created yet another
+framework based on Zope 3 called Grok.  The original Zope which is now
+known as Zope 2 is also widely used.
+
+
+Organization of the book
+------------------------
+
+This book has divided into multiple chapters.  Summary of each
+chapter is given below.
+
+
+Introduction
+~~~~~~~~~~~~
+
+This chapter introduce Zope 3 with an overview and scope of the book,
+then briefly go through the history of Zope 3.  Later discuss
+organization of the book.  And finish with a thanks section.
+
+
+Getting Started
+~~~~~~~~~~~~~~~
+
+This chapter begins with installation details of Python and Zope 3.
+Then introduce Buildout, the build system we use to setup an isolated
+Python working environment and its configurations.  Later, it explore
+setting up development sandbox using Buildout.  A simple application
+is developed further and it ends with a `hello world` page.  During
+the application development we see how to use ZMI (Zope Management
+Interface) briefly.  This chapter also provides a brief overview of
+important packages and installation of additional packages.
+
+
+Development Tools
+~~~~~~~~~~~~~~~~~
+
+This chapter is going to the details about how to develop a web
+application using Python and Zope components.  You should familiarize
+some essential tools like Python eggs, setuptools and buildouts.  If
+you are already familiar with these you may skip this chapter.
+
+
+Interfaces
+~~~~~~~~~~
+
+This chapter introduce the concept of interfaces.  If you are already
+familiar with this you may skip this chapter.
+
+
+Component Architecture
+~~~~~~~~~~~~~~~~~~~~~~
+
+This chapter introduce Zope component architecture.  If you are
+already familiar with this you may skip this chapter.
+
+
+Thanks
+------
+
+This book would not be possible if Zope 3 did not exist.  For that,
+the I would like to thank all developers of Zope 3.  I am grateful to
+Stephan Richter for allowing me to use his book and training material
+for this work.

Added: zope3book/trunk/source/skinning.rst
===================================================================
--- zope3book/trunk/source/skinning.rst	                        (rev 0)
+++ zope3book/trunk/source/skinning.rst	2009-02-20 19:10:14 UTC (rev 96847)
@@ -0,0 +1,190 @@
+Skinnig
+=======
+
+Motivation
+
+* Need to build sites with equal/similar features, but different look
+  and feel
+
+* Variation of Look and Feel can be simple or complex
+
+  - Exchange a CSS file and some images
+
+  - Reconfigure the application to have different UI components, such
+    as widgets, tables, O-wrap, etc.
+
+* Often need to mix and match UI components from multiple packages
+
+The level of customization of Zope (2 and 3) has been a strong point
+for years. Initially the UI was customized relying on implicit
+acquisition, where it was simply a matter of adding an object higher
+in the object path to customize the UI. Since implicit acquisition is
+often hard to debug, the CMF introduced the concept of skins, where a
+skin describes the look and feel of a site. Skins could acquire from
+other skins explicitly.
+
+In Zope 3 the concept of skins was reconsidered and re-implemented to
+use the component architecture.
+
+Layers
+
+* Define the "feel" of a site
+
+* Contain presentation logic
+
+* Common artifacts: pages, content providers, viewlet managers, and
+  viewlets
+
+* Developed by Zope 3 Python developers
+
+Skins
+
+* Define the "look" of a site
+
+* Common artifacts: templates and resources (CSS, Javascript, etc.)
+
+* Use layers to retrieve the data for templates
+
+* Developed by HTML and Graphic Designer/Scripter
+
+Layers versus Skins
+
+* Both are implemented as interfaces
+
+* Zope 3 does not differentiate between the two
+
+* In fact, the distinction of layers defining the "feel" and skins
+  the "look" is a convention. You may not want to follow the
+  convention, if it is too abstract for you, but if you are
+  developing application with multiple look and feel, I strongly
+  suggest using this convention, since it cleanly separates concerns.
+
+
+* Both support inheritance/acquisition
+
+This is realized through a combination of interface inheritance and
+component lookup techniques. We will discuss this in more detail
+later.
+
+Skins are directly provided by a request
+
+Core Skins
+----------
+
+* Access skin using ++skin++Name after the server root
+
+* Core Skins that are part of the repository
+
+  - Rotterdam -- the default skin shown
+
+  - Boston -- a newer skin featuring viewlets
+
+  - Basic -- a skin with no layout styles
+
+  - Debug -- based on Rotterdam, shows debug information upon
+    failures
+
+* Try http://localhost:8080/++skin++Boston
+
+Unfortunately, it is hard to reuse the UI components developed for
+these skins, since they still rely on the not so flexible macro
+pattern. Thus, it is better if you start from scratch. This will also
+avoid a lot of the overhead that comes with the over-generalized core
+skins.
+
+A New Skin
+----------
+
+* Views registered for default layer by default
+  zope.publisher.interfaces.browser.IDefaultBrowserLayer
+
+* Default layer contains a lot of things we do not need (security
+  concerns)
+
+* Since pretty much everything in zope.app is registered into the
+  default layer, it has an uncontrollable amount of junk in it. It is
+  very hard to verify that all those registrations fulfill your
+  security needs. Another problem is that views might be available
+  that you do not want to be available.
+
+
+* Always want to develop skins from scratch
+
+* Some registrations in the default layer are very useful
+
+* Examples of those useful registrations include error views, traversal registrations, and widgets.
+
+* Useful set of registrations collected in the minimal layer z3c.layer.minimal
+
+* Add the z3c.layer.minimal package to your project dependencies
+
+
+Setting up a Layer
+------------------
+
+Write an interface for the layer that inherits the minimal layer::
+
+  from z3c.layer import minimal
+
+  class IHelloWorldLayer(minimal.IMinimalBrowserLayer):
+      """Hello World Application Layer"""
+
+
+Change all page, viewletmanager, and viewlet directives to specify
+this layer:
+
+  layer=".interfaces.IHelloWorldLayer"
+
+Once you changed those registrations, the helloworld.html page is not
+available anymore in the core skins. The templates by themselves do
+not matter.
+
+
+Setting up a Skin
+~~~~~~~~~~~~~~~~~
+
+Write an interface for each new skin that inherits the Hello World
+application layer::
+
+      class IBasicSkin(IHelloWorldLayer):
+          """Basic Skin for Hello World App."""
+
+Register the interface as a skin interface::
+
+  <zope:interface
+      interface=".interfaces.IBasicSkin"
+      type="zope.publisher.interfaces.browser.IBrowserSkinType"
+      name="HWBasic"
+      />
+
+Register all templates for this skin by adding the layer attribute:
+
+      layer=".interfaces.IBasicSkin"
+
+
+Using the Skin
+~~~~~~~~~~~~~~
+
+Access it via: http://localhost:8080/++skin++HWBasic
+
+Hide skin traversal step by using Apache's Virtual Hosting feature
+
+To change the default skin to something else use:
+
+  <browser:defaultSkin name="HWBasic" />
+
+Simply specifying the browser:defaultSkin directive in your
+configuration file will not work, since it has been specified in
+zope/app/zcmlfiles/browser.zcml already. You can either change the
+skin at this location or use the zope:includeOverrides directive,
+which will override the any included directives.
+
+Exercise
+--------
+
+* Develop the Hello World application layer.
+
+* Develop two skins based on this layer.
+
+* Write some tests that specifically test the difference between the
+  skins.

Added: zope3book/trunk/source/testing.rst
===================================================================
--- zope3book/trunk/source/testing.rst	                        (rev 0)
+++ zope3book/trunk/source/testing.rst	2009-02-20 19:10:14 UTC (rev 96847)
@@ -0,0 +1,96 @@
+Testing
+=======
+
+
+Unit testing
+------------
+
+This chapter will discuss about unit testing and integration
+testing. Doctest-based testing is heavily used in Zope 3. And test
+driven development (TDD) is prefered in Zope 3.  To explain the idea,
+consider a use case. A module is required with a function which
+returns "Good morning, name!". The name will be given as an
+argument. Before writing the real code write the unit test for
+this. In fact you will be writing the real code and it's test cases
+almost in parallel. So create a file named example1.py with the
+function definition::
+
+  def goodmorning(name):
+      "This returns a good morning message"
+
+See, you have not yet written the logic. But this is necessary to run
+tests successfully with failures!. Ok, now create a file named
+example1.txt with test cases, use reStructuredText format::
+
+  These are tests for example1 module.
+
+  First import the module:
+
+    >>> import example1
+
+Now call the function goodmorning without any arguments::
+
+  >>> example1.goodmorning()
+  Traceback (most recent call last):
+  ...
+  TypeError: goodmorning() takes exactly 1 argument (0 given)
+
+Now call the function goodmorning with one argument::
+
+  >>> example1.goodmorning('Jack')
+  'Good morning, Jack!'
+
+See the examples are written like executed from prompt. You can use
+your python prompt and copy paste from there. Now create another file
+test_example1.py with this content::
+
+  import unittest
+  import doctest
+
+  def test_suite():
+      return unittest.TestSuite((
+          doctest.DocFileSuite('example1.txt'),
+          ))
+
+  if __name__ == '__main__':
+      unittest.main(defaultTest='test_suite')
+
+This is just boilerplate code for running the test. Now run the test
+using python2.4 test_example1.py command. You will get output with
+following text::
+
+  File "example1.txt", line 16, in example1.txt
+  Failed example:
+      example1.goodmorning('Jack')
+  Expected:
+      'Good morning, Jack!'
+  Got nothing
+
+
+Now one test failed, so implement the function now::
+
+  def goodmorning(name):
+      "This returns a good morning message"
+      return "Good morning, %s!" % name
+
+Now run the test again, it will run without failures.
+
+Now start thinking about other functionalities required for the
+module. Before start coding write about it in text file. Decide API,
+write test, write code, than continue this cycle until you finish
+your requirements.
+
+
+Running tests
+-------------
+
+By conventions your test modules are put in tests module under each
+package. But the doctest files can be placed in the package
+itself. For example if the package is ticketcollector. Then the main
+doctest file can be placed in ticketcollector/README.txt. And create
+a sub-package zopetic.tests, under this package create test modules
+like test_main.py, test_extra.py etc.  To run the unit tests, change
+to instance home::
+
+  $ cd ticketcollector
+  $ ./bin/test



More information about the Checkins mailing list