13 min read

(For more resources on Plone, see here.)

Prerequisites

Pre-built packages for Zope and Plone are available for many operating systems. These can be tempting, but as developers it is normally better to configure the environment ourselves, in order to fully understand and control it. During development, we need write access to the Python code and configuration files. We may also need to run different versions of Zope and Plone in parallel. We will assume that you have at least the following as part of your regular development environment:

 

  • Python 2.4. We will assume that Python 2.4 gets invoked when you run python on the command line. Unfortunately, Zope, at version 2.10, does not yet support Python 2.5. Note that many Linux distributions have two packages for Python—one containing the binaries, and one containing header files (typically called python-dev or something similar). You will need both in order to compile Zope.
  • PIL, the Python Imaging Library (http://www.pythonware.com/products/pil), should be installed for this Python interpreter.
  • elementtree, an XML processing library, is required for Plone to start up. Most operating systems have packages for this. It can also be downloaded from http://effbot.org/zone/element-index.htm.
  • A programmer’s text editor. Preferably one with Python, XML/HTML and CSS syntax highlighting. You should set up your editor so that a tab/indent is output as four spaces. This makes Python development a lot more predictable.
  • A shell. Most examples in this book will show a Bash interpreter shell, though we will cover Windows syntax when it differs significantly. Bear in mind that path separators on Windows are backslashes (), while other environments use forward slashes (/). Also, environment variables on Windows are referred to as %NAME%, while in most Unix shells, including Bash, variables are dereferenced with $NAME.
  • A Subversion client. We will show the command line client syntax, but you can use a graphical client if you are more comfortable with that. Subversion can be obtained from http://subversion.tigris.org.
  • A C compiler. You will need this to compile Zope. The venerable gcc is fine on UNIX-like systems. On Windows you probably want mingw32 (http://www.mingw.org). Alternatively, you can use a Zope Windows installer to get a binary Zope distribution.

 

Quick Start

Understanding your development environment is an important step in becoming a productive developer. If you need to get up and running quickly, however, and you have the prerequisites outlined above in order, here are the key steps.

We will assume you have Python 2.4 as your main Python interpreter. First download easy_install if you do not have it already, and use it to install ZopeSkel:

  $ wget http://peak.telecommunity.com/dist/ez_setup.py
  $ python ez_setup.py
  $ easy_install ZopeSkel

Note: If you do not have wget (e.g. because you are using Windows), you can just as easily download the ez_setup.py script using a web browser. When you run this script, it will install the easy_install binary to a directory that may not already be in your system PATH. Watch the ez_setup.py output to identify this directory. If it is not in your PATH, you should add it, allowing you to run easy_install as shown.

Then, use paster, which was installed as a dependency of ZopeSkel, to create a new buildout. This folder holds our source code and dependencies, including the Zope application server:

  $ paster create -t plone3_buildout myproject

You can accept the defaults for all the questions, except for the password, which you must enter. Then, build the environment like so:

  $ cd myproject
  $ python bootstrap.py
  $ ./bin/buildout

Note: If you are using Windows, be sure to read the README.txt file that is generated in the myproject directory before running the buildout command.

This last step may take some time, and you will need a live Internet connection.When it is complete, you can start Zope with:

  $ ./bin/instance fg

Go to http://localhost:8080/manage and you should see the Zope Management Interface. Use the drop-down box to add a Plone Site. If you call this mysite, it will beaccessible from http://localhost:8080/mysite.

Glossary

Let us now take a step back and consider our development environment in more detail.

The table below summarizes the various terms and technologies that you will encounter in this chapter. It pays to be familiar with these names, because you will find them again not only throughout this book, but also in other Plone documentation.

Term

Definition

Zope installation

Zope consists of Python code, C extensions, configuration files, documentation, scripts, and utilities. Collectively, these are known as the Zope installation.

Software home

The part of the Zope installation that contains the main Zope runtime. This is found in the lib/python directory of the Zope installation. The full path is assigned to the $SOFTWARE_HOME environment variable when Zope is run.

Zope instance

The same Zope installation can be used to power multiple Zope servers, possibly running concurrently on different ports. Each instance has a directory containing a configuration file, instance-specific software components (e.g. an installation of Plone), and the local Zope database storage.

Instance home

When a Zope instance is running, the $INSTANCE_HOME environment variable refers to the directory where the instance is set up.

Package

A generic term for a distributable bundle of Python modules and supporting files.

Product

The traditional way to redistribute software for Zope 2 is in a “Product”, which we will sometimes refer to as an “old-style Product”. Products are placed in a special directory (Products/) and automatically discovered by Zope. The term “product” is also used more generally to refer to add-on components that extend Plone, even if they are not actually packaged as old-style Products.

Egg

A more generic and flexible alternative to products. Eggs are not specifi c to Zope, and Zope has only recently been made egg-aware. In addition to code, eggs contain metadata such as version, dependencies, and license information. Egg management tools can use this information to manage concurrent versions or automatically fetch dependencies, for example.

$PYTHONPATH

The $PYTHONPATH environment variable lists the directories containing Python packages that should be available at run time. It can also reference specific eggs. You should not have to set this manually.

setuptools

A Python library, which extends Python’s built-in distutils package to support extended egg metadata and offers enhanced functionality when using software packaged as eggs.

The Cheese Shop

Also known as PyPI (Python Package Index). An online repository of Python eggs. Anyone can upload a package here. Egg-aware tools can use the Cheese Shop to locate dependencies and download them automatically when installing other eggs.

easy_install

A command-line tool, which searches the Cheese Shop for a given package, and downloads and installs it. Note that, by default, easy_install puts packages in the global site-packages folder for the Python interpreter that was used to install easy_install itself. Normally, we want our Plone packages to be local to a specific Zope instance, necessitating different tools.

paster (Paste Script)

paster, part of the Python Paste package, is a command runner. The paster create command invokes Paste Script templates, which are used to create skeleton packages based on command-line options and questions.

ZopeSkel

A collection of Paste Script templates for Zope and Plone development. We will use this to create new egg-ready packages, as well as the buildout that manages our development environment.

Buildout (zc.buildout)

A “buildout”, using the zc.buildout toolset, is a self-contained environment that is controlled through a single configuration file (buildout.cfg). We will use it to download, install, and configure Zope, Plone, and other dependencies. Buildouts are “repeatable”, meaning that they can be used to replicate a particular setup across multiple servers or developers’ machines.

 

 

Understanding Eggs and Setuptools

Python eggs are not specific to Zope or Plone. However, since Zope has only recently become egg-aware, they are new to many developers.

Traditionally, almost all Zope add-on products, including Plone, have been distributed as Zope products. These are fairly easy to manage—you typically copy or symlink them into $INSTANCE_HOME/Products. Zope will scan this directory on startup, taking care of any product initialization and registration.

However, code inside products is nearly impossible to re-use outside Zope because Zope does magic things with the Products.* namespace. Further, the namespace quickly becomes crowded, which deters developers from breaking up functionality into smaller, more re-usable and better-isolated packages.

The Zope 3 philosophy is to be as close to “plain Python” as possible, and that means distributing code as such small packages. So long as its dependencies are in order, any package should be able to run in any environment. For example, the zope.interface package is used by the Twisted project, which is not otherwise dependent on Zope. This design goal has made it much easier to adopt Zope 3 packages in Zope2 and Plone.

Starting with Plone 3, the Plone community has also embraced “plain Python” packages and uses them wherever possible. A number of packages, such as plone.memoize and plone.portlets are generic enough to work without any dependencies on the rest of Plone. Others are more specific to Plone and live in the plone.app namespace, such as plone.app.layout and plone.app.portlets, thelatter containing Plone-centric extensions to the generic plone.portlets package.

All that is needed to use these packages is a sensible $PYTHONPATH. Thus, we can copy or link packages into $INSTANCE_HOME/lib/python/plone/memoize, lib/python/plone/portlets, lib/python/plone/app/portlets, and so forth for Zope to find them. This works, but it is pretty tedious when there are many packages, and it can become outright confusing when there are nested namespaces being used bymultiple packages.

Luckily, other Python programmers have solved these problems, first creating distutils, then its successor setuptools and with setuptools, Python eggs.

Note: For the setuptools documentation, see http://peak.telecommunity.com/DevCenter/setuptools.

Installing Eggs

When using setuptools, each project or package lives in a directory that has a toplevel setup.py file. This contains metadata about the package itself, and declares its current version as well as any dependencies. Dependencies can be specifieddown to particular versions (e.g. “>=0.2,<1.0” means “later than version 0.2 but before version 1.0”). When a package is installed, setuptools will attempt to fulfilldependencies by downloading and installing them if necessary.

If you have a setuptools-enabled package, you can use setup.py to install it globally, by running:

  $ python setup.py install

This will copy the source code to the system-wide Python site-packages directory. Having to re-run this command each time you make a change can make development a little awkward, so while you are working on a particular package,you can install a development egg. This is essentially a link to the package’s source code that ensures it is added to the $PYTHONPATH. To install a development egg, run:

  $ python setup.py develop

New packages can be released as binary eggs for distribution, which are just ZIP files of the package with some additional metadata. You can build an egg from within apackage by running:

  $ python setup.py bdist_egg

The new egg will be placed in the dist sub-directory, which will be created if necessary.

Eggs can be uploaded to the Cheese Shop, also known as PyPI (the PythonPackage Index). This central repository makes it easy to fi nd packages. You canbrowse packages at http://cheeseshop.python.org/pypi. New packages can beuploaded via this website, or directly from the command line:

  $ python setup.py egg_info -RDb “” sdist bdist_egg register upload

You will be asked to specify or create a Cheese Shop account if this is the first time you run this command. A script called easy_install lets you search the Cheese Shop (or a similar index, if you specify a URL) for packages that it can download and install into the global Python environment. Dependencies will be included automatically. This is great for simple libraries and end-user applications, but less great when you are working on multiple Zope projects that may have different version requirements. This is why we tend to manage our eggs inside $INSTANCE_HOME or, as you will see in the next section, as part of a controlled buildout.

Note: A tool called workingenv.py can create a mini-environment where global commands are restricted to a particular directory. We will not cover workingenv in this book, but you can download and read more about it at http://cheeseshop.python.org/pypi/workingenv.py.

When eggs are activated (either explicitly, or implicitly by being unambiguouslyfound in the $PYTHONPATH), they can be discovered by other packages listening for plug-ins, using a mechanism called entry points (see http://peak.telecommunity.com/DevCenter/setuptools#dynamic-discovery-of-services-and-plugins).

Zope does not yet directly use entry points, so we will not be covering them inany detail here. However, entry points are a very powerful system, and there areproposals to let Zope’s discovery of packages use entry points instead of scanningmagic directories.

With eggs, we therefore have the tools to manage multiple packages, from differentdevelopers and repositories, possibly across multiple versions. By using the packagemanagement tools that the rest of the Python community employs, we also make iteasier to re-use other libraries and share our own code with outside developers.

Automating the Build Process with zc.buildout

Creating a Zope instance and copying or linking packages into $INSTANCE_HOME/lib/python as is done in the manual process is not too difficult, but this approach has a few limitations.

  • The process is manual and cumbersome to repeat across multiple environments.
  • Multiple developers working on the same project may share the code in eggs and products by using a version control system such as Subversion. However, each developer would be responsible for setting up their development environment, and subtle differences may cause problems that are difficult to debug.
  • Packages are installed manually, and so cannot benefit from setuptools’ ability to manage dependencies and updates.
  • Complex deployments that include other libraries, non-python code, or specific configurations will also need to be taken care of manually.

Luckily, there are tools to make deployment easier. zc.buildout is one such tool, written largely by Zope founder Jim Fulton at Zope Corporation. It makes heavyuse of eggs and setuptools and is very flexible in supporting a wide range of deployment scenarios.

Central to a buildout (i.e. what zc.buildout is managing for us) is a file called buildout.cfg. This specifies various options, including a list of parts, which will be executed when the buildout is run. Each part is associated with a recipe—a named egg, which will be called upon to parse the options provided, and perform a particular task, such as building a Zope instance or downloading Plone.

A project-specific buildout directory can be checked into a version control system and shared among developers. It can also be used to replicate a particular environment across different servers with a high degree of predictability.

By writing custom recipes, you can make zc.buildout do almost anything. Writing a recipe is not particularly hard, and there are plenty of examples and generic solutions available. However, we will not cover creating new recipes in this book, because all the recipes we need already exist.

LEAVE A REPLY

Please enter your comment!
Please enter your name here