|
|
BROWSE
All Titles WordPress Web Services SOA BPEL Web Graphics & Video Web Development RAW Portugues, Espanol, Italiano, French PHP/MySQL Oracle Open Source Networking & Telephony Moodle Microsoft & .NET Linux Servers jQuery Joomla! JBoss Java e-Learning e-Commerce Dynamics Drupal CRM Cookbook Content Management Beginner Guides Architecture and Analysis AJAX Future Titles Recently Published Titles |
Setting up the Plone Development Environment
Before we can start building our application, we should set up a suitable development environment. This should as closely as possible mirror the final live server configuration, so that we can test our software locally before deploying it. The environment should also provide appropriate tools to support us during development. PrerequisitesPre-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:
Quick StartUnderstanding 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 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 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. GlossaryLet 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.
Understanding Eggs and SetuptoolsPython 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 EggsWhen 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.buildoutCreating 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.
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.
Installing Paste Script and ZopeSkelTo create the buildout.cfg file and some necessary boilerplate, we will make use of Paste Script, a tool for creating project skeletons from templates. Later, we will alsouse Paste Script to create new packages following standard conventions.Paste Script is an extensible system with which other packages (or rather, eggs) can register new templates (using entry points). For Zope and Plone development, the ZopeSkel package provides several useful templates. You can fetch ZopeSkel using easy_install. If you do not have easy_install, you must download it: $ wget http://peak.telecommunity.com/dist/ez_setup.py $ python ez_setup.py If you do not have wget (e.g. you are using Windows), download the ez_setup.py script using a web browser instead, and run it with python as shown.Keep an eye on where the script puts the easy_install executable. Depending on your setup, you may need to add this to your $PATH environment variable or reference it by an absolute directory. Adding the script's directory to your $PATH maybe a good idea, though, since the paster command and other egg-installed binaries will go in the same place. Now, simply run: $ easy_install ZopeSkel This will find ZopeSkel in the Cheese Shop, download it, and install it, including its dependencies. Creating and Customizing the BuildoutNow we can create our project's buildout, using a Paste Script template fromZopeSkel:$ paster create -t plone3_buildout optilux If you run this command, you will be asked a series of questions, including:
Buildout will create a new environment, containing a generated buildout.cfg file and some standard directories. To bootstrap the buildout to get the standard zc.buildout tools, run: $ cd optilux This step is only needed once. We are now ready to build the system. Simply run: $ ./bin/buildout This may take a long time, depending on the speed of your computer and internet connection. It will download and build Zope, download and install Plone, and configure the two. When it is finished, you can start Zope by running: $ ./bin/instance start Stop it again with: $ ./bin/instance stop Note: If Zope fails to start or you cannot find Plone Site in the list of addable types in the ZMI, you are most likely missing a dependency such as PIL or elementtree. Start Zope in the foreground using ./bin/instance fg (with debug mode on) and look out for an error message in the terminal window.The Buildout Configuration FileThat is all that is needed to get started. To understand what is going on, though, let us take a look at the buildout.cfg file that was generated for us (slightly abbreviated): [buildout] Starting from the top, this file defi nes various things that will happen when our buildout is run:
If for any reason buildout.cfg is changed, or if you wish to obtain recent updates to any eggs listed, you should run ./bin/buildout again. You can often save sometime by running buildout in offline and non-updating mode, where it will not check for updates to eggs and products online, by using: $ ./bin/buildout -No To get a full explanation of the various options available, run: $ ./bin/buildout --help The Buildout DirectoryLet us now take a look at the directories zc.buildout creates for us.
Avoiding Duplication between BuildoutsIf as a developer you are managing several projects with different buildouts, you may want to share some source code between them. We have already seen the options that allow you to specify shared Zope 2 installations and Plone product directories. This will save considerable disk space, but bear in mind that old-styleZope products are not individually versioned, so any changes or upgrades will affect all instances where they are referenced. It is also possible to share an eggs directory between different buildouts. Unlike products, eggs carry version information, and so it is possible to keep different versions installed simultaneously. For example, if one egg was referenced in buildout.cfg as my.package==0.9 and another buildout used my.package>=1.0, two versions could be downloaded and activated as appropriate. The eggs directory to use is controlled by the eggs-directory option in the[buildout] section of buildout.cfg. Rather than having to add this to each project, however, we will put it in the defaults.cfg file, which zc.buildout examines to pickup additional options in addition to what is in the buildout.cfg file. In your home directory, create a directory called .buildout. Within it, add another directory called eggs, and a file called default.cfg, containing: [buildout] Similarly, you can specify a shared archive downloads directory, using the download-directory option. For example, you can create a directory called downloads next to the aforementioned eggs directory, and add the following to default.cfg: [buildout] This file can be used for other defaults if necessary. In particular, if you need to use a specific Python interpreter instead of the default system-wide one, use a line like the following: executable = /path/to/python2.4
Additional Development ToolsDuring development, we typically rely on various tools to help us debug our code and inspect Plone and Zope. The oldest of these is the DocFinderTab, a Zope product that adds a Doc tab to every object in the ZMI. This tab lists the class and base classes for the object being inspected, including methods and their docstrings.
By using a regular expression in the Filter box at the top, you can look for specific methods. If DocFinderTab is old-school, Clouseau is hip and happening. It is essentially an in-browser Python shell, using JavaScript and AJAX technologies. It supports two modes:
Here is an example of Clouseau inspecting the default Plone front page, changing the title and saving the results:
Please refer to the Clouseau help, under the Clouseau control panel, for more information. Clouseau is a full, unprotected interpreter shell with access to all of Zope and the currently installed products and packages. A fine demo of Clouseau is to use it to delete your entire Plone instance. Obviously, it should be kept far, far away from production servers, and by default it is only available when Zope runs in debug mode. Being able to prototype things in the browser, inspect the innards of any object in Zope, and make changes on the fly can be incredibly useful, though. Just keep a backup of your Data.fs file.Both DocFinderTab and Clouseau are distributed as old-style products in separate archives. To obtain and install them, edit buildout.cfg and modify the [productdistros] section like this: [productdistros] These URLs are correct at the time of writing. You may want to check for newerversions, especially of Clouseau, at http://plone.org/products/clouseau. Now, we can re-run buildout and start Zope in debug mode: $ ./bin/buildout -N We should then be able to install Clouseau from the Plone control panel.DocFinderTab requires no explicit installation. Learning to Help YourselfDuring development, there will probably be times when you are stumped. Plone is fairly well-documented, but the documentation is certainly not perfect. The mailing lists and chat room are great resources if you need help, but it is also very importantto learn how to help yourself. Use the Source, Luke!Python's readability is both a blessing and a curse. A blessing, because it is normally possible to read the source code and find out what is going on. A curse, because this sometimes makes developers a little lax about documentation. One of the first hurdles new developers should overcome is any undue respect for the Python files that make up Zope and Plone. There is (almost) nothing magical about them. In this chapter, we have seen where the source code lives: core Zope modules in $SOFTWARE_HOME, third-party products in the products folder, and eggs in lib/python or the eggs folder managed by buildout. Get used to searching for code in these files using grep or equivalent graphical tools, opening them, and looking for specific classes and methods. Seeing what a piece of code does can often be faster than looking up documentation or examples. As time goes by, you will find that a few packages come up again and again, and finding code will be easier. You can of course change these files as well. A backup is advisable, but if you think that temporarily raising an exception or printing a message from somewhere deep inside Zope helps you to solve a problem, go right ahead. It is probably a bad idea to make permanent changes this way, however, because those changes will be overwritten if you upgrade or re-install the particular component. In the next chapter, we will learn more about other ways of customizing code Zope and Plone. However, if you find a bug, please report it, and attach a patch if you can! Note: Plone bugs can be reported at http://dev.plone.org/plone. Zope bugs are collected at http://zope.org/Collectors/Zope, and CMF bugs at http://zope.org/Collectors/CMF. Here are some examples of where you may look for source code if you see an import or a description of a module in this book:
Become Familiar with the DebuggerIt is also very important to be familiar with pdb, the Python debugger (see http://docs.python.org/lib/module-pdb.html). To insert a breakpoint in your code—or in some other code that you are trying to debug—add the following line and (re-)start Zope in the foreground in a terminal: import pdb; pdb.set_trace() When the line is encountered, execution will stop, and the terminal will display: (pdb) This is the interactive pdb prompt. Type help and press Enter to see available commands: the most important ones are pp—to print a variable or the result of an expression, n—to step to the next line, s—to step into a function call, l—to show a listing of the source code around the current execution point, and c—to stop debugging and continue execution. If you want to quickly test syntax or libraries, you can run Python's interactive interpreter. To make sure you have all the same eggs and packages available as Zope will when it starts up, run: $ ./bin/zopepy Write Tests for EverythingFinally, the biggest favor you can do yourself as a developer is to learn to write unit tests. To learn more about tests, see http://plone.org/documentation/tutorial/testing. Without unit tests, there is no telling whether your code is working, and whether you have inadvertently broken it. Since tests are normally small and isolated, they are also a great starting point for diagnosing problems or examining the behavior of other components. Try writing a small test and placing a pdb break point in it, stepping into other code as necessary. SummaryIn this article, we have seen:
Martin Aspeli is an experienced Plone consultant and prolific Plone contributor. He served on the Framework Team for Plone 3.0, and is responsible for many new features, such as the improved portlets infrastructure and the “content rules” engine. He is also the current leader of the Plone Documentation Team, and has written a number of well-received tutorials available on plone.org.
Books from Packt
|
BOOK ![]() Professional Plone Development See More BOOK ![]() Building Websites with Plone See More |
| ||||||||