python
Feb 15, 2010
Do not use "print". Again plone_log is your friend
An unexpected behaviour I found when writing test for a product. Use "print" command for logging is bad if you want to perform functional tests.
In early days on Plone I always used this API for logging:
context.plone_log("That's a log message")
This will give you a log message like this:
2010-02-15 09:56:32 INFO Plone Debug: That's a log message
I don't know or remember if the Python print command always worked on Plone, but right now you can use it freely.
I found that sometimes I used print, just because is simpler (and I don't need any context as plone_log).
Now the problem... use plone_log (or every other use of python logging system) is safe when writing functional doctests.
The print command isn't! If you are testing code that use print, you must be aware of its output writing test. For example:
This is a fake doctest.
Let's say that calling the button below will run some code that use Python "print" command.
For example for write "Hello".
>>> browser.getControl('button').click()
'Hello'
I don't like this... this is not a useful test!
This is very annoying!
So? It's better to not use print for logging messages, but rely on other logging APIs.
Jan 13, 2010
Install Plone 4 on OSX Leopard e Snow Leopard (from scratch)
Install Plone 4 without Unified Installer is easy.
Trying Plone 4 is easy.
The following steps are tested with OSX 10.6 Snow Leopard and OSX 10.5 Leopard.
The first step is to obtain the compiler to build Python from source.
On OSX, to install the gcc compiler, download the Xcode package from http://connect.apple.com/. You’ll need to register for an Apple Developer Connection account. Once you’ve registered, login and click Download Software and then Developer Tools. Find the Download link
Xcode 3.2.1 Developer DVD (Disk Image)
Be careful: Xcode 3.2.1 is for OSX 10.6 Snow Leopard and Xcode 3.1.4 is for OSX 10.5 Leopard.
First: create a temp folder:
mkdir -p /Users/stefano/Devel/tmp
cd /Users/stefano/Devel/tmp
Plone 4 needs Python 2.6; it is easy build Python from source. The great advantage is that, in this way, all files will be in a folder leaving your OS "clean".
Download the latest version 2.6 release from http://www.python.org/download/releases/2.6.4/
Move the file (Gzipped source tar ball) Python-2.6.4.tgz in the "temp" folder and uncompress it:
tar zxf Python-2.6.4.tgz
cd Python-2.6.4
Create the Python destination folder:
mkdir -p /Users/stefano/Devel/python/2.6/
cd /Users/stefano/Devel/tmp/Python-2.6.4
before you can build your Python first you must configure it.
From the folder /Users/stefano/Devel/tmp/Python-2.6.4 type the command:
./configure --prefix=/Users/stefano/Devel/python/2.6/
Then to build your Python type:
make
To install the Python binary, library modules, shared library modules, include files, configuration files, and the manual page, just type:
make install
Download the Python Imaging Library (the "all platform" version) from
http://www.pythonware.com/products/pil/
Move the downloaded file in /Users/stefano/Devel/tmp/
tar zxf Imaging-1.1.6.tgz cd /Users/stefano/Devel/tmp/Imaging-1.1.6
Install Python Imaging Library in your Python environment:
/Users/stefano/Devel/python/2.6/bin/python2.6 setup.py install
cd /Users/stefano/Devel/
Then download the Plone source:
svn co http://svn.plone.org/svn/plone/buildouts/plone-coredev/branches/4.0/ plone4 cd plone4
Then bootstrap Plone:
/Users/stefano/Devel/python/2.6/bin/python2.6 ./bootstrap.py
Then run the buildout:
./bin/buildout
Start Plone:
./bin/instance fg
Then type this URL in your browser:
http://localhost:8080
Enjoy your new Plone 4!
If you want to test new experimental functionality you can use configuration files in the folder "exeperimental" in the plone folder (Users/stefano/Devel/plone4)
For example to try Deco relaunch the buildout:
./bin/buildout -c experimental/deco.cfg
For more information read the instructions at the beginning of the configuration file "experimental/deco.cfg".
Nov 13, 2009
How to write funkload test in few minutes
After PloneConf2009 I noticed interesting changes in collective.recipe.funkload. Right now writing a simple test for funkload is just few steps.
After Plone Conference 2009 I noticed interesting changes in collective.recipe.funkload and in collective.funkload itself. Right now writing a simple stress test for funkload is much easier - you can do it in few steps.
Let's start with creating a simple package called mytest:
$ ls ./mytest boostrap.py buildout.cfg setup.py src $ ls ./mytest/src/mytest __init__.py tests $ ls ./mytest/src/mytest/tests __init__.py test_Simple.py Simple.conf
buildout.cfg is also simple:
[buildout]
develop = .
parts = funkload
[funkload]
recipe = collective.recipe.funkload
url = http://www.plone.org
eggs = mytest
where www.plone.org is the url to the site you want to test (it doesn't need to be on you localhost)
Now the funkload test configuration file (Simple.conf):
[main]
title=Simple
label=Simple test for blog.redturtle.it
description=Simple test scenario
[test_Simple]
description=Simple test scenario
[ftest]
log_to = console file
log_path = Simple-test.log
result_path = Simple-test.xml
[bench]
cycles = 5:15:30
duration = 100
startup_delay = 2
sleep_time = 2
cycle_time = 2
log_to = file
log_path = Simple-bench.log
result_path = Simple-bench.xml
sleep_time_min = 2
sleep_time_max = 2
In this example most important bench configurations:
- cycles = 5:15:30 - contains 3 cycles: for 5, 15 and 30 concurrent users
- duration = 100 - duration of one cycle in seconds
- startup_delay = 2 - time to wait between starting-up threads in seconds
- sleep_time = 2 - time to wait between test in seconds
- cycle_time = 2 - time to wait between cycle in seconds
And the funkload test scenario (test_Simple.py)
import unittest
from collective.funkload import testcase
class Simple(testcase.FLTestCase):
"""Simple load test scenario."""
def setUp(self):
"""Setting up test."""
self.logd("setUp")
self.label = 'Simple test'
self.server_url = self.conf_get('main', 'url')
def test_ReadOnly(self):
self.get(self.server_url + "/",
description="Get /")
self.get(self.server_url + "/login_form",
description="Get /login_form")
self.post(self.server_url + "/login_form", params=[
['came_from', self.server_url],
['form.submitted', '1'],
['js_enabled', '0'],
['cookies_enabled', ''],
['login_name', ''],
['pwd_empty', '0'],
['__ac_name', 'admin'],
['__ac_password', 'admin'],
['submit', 'Login']],
description="Post for login a user /login_form")
self.get(self.server_url + "/folder/document1",
description="Get /folder/document1")
self.get(self.server_url + "/logout",
description="Get /logout")
def tearDown(self):
"""Setting up test."""
self.logd("tearDown.\n")
def test_suite():
return unittest.makeSuite(Simple)
additional_tests = test_suite
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
It's a very simple scenario in which we are:
- opening plone site (get /)
- opening login_form (get /login_form)
- sending a post with login credentials (post /login_form)
- opening a document (get /folder/document1)
- logout (get /logout).
Now you need to bootstrap the buildout:
$ cd mytest $ python bootstrap.py
lunch the buildout:
$ ./bin/buildout
and lunch the bench:
$ ./bin/funkload bench -t mytest.tests.test_Simple
final report you can find in your buildout directory:
$ ls ./var/funkload/reports/2009-11-11-19-40-20 test_Simple-20091111T194020 $ ls ./var/funkload/reports/2009-11-11-19-40-20/test_Simple-20091111T194020 funkload.css index.html index.rst tests.data tests.gplot tests.png
For more information please check:
Nov 07, 2009
RuPy conference
Short summary about RuPy - strongly dynamic conference. The philosophy of RuPy is to put togheter Python & Ruby experts with young programmers and to support a good communication channel for East-West exchange of prospective ideas.
I have been delegated as a RedTurtle member to join RuPy conference that has been held in Poznan, my hometown city.
The idea behind the conference is to try to animate central- and east-european Python and Ruby communities. By inviting experts we want to broaden our knowledge and undersanding of presented concepts. The conference is meant to serve the exchange of ideas on the scientific ground, that is use of mentioned languages for certain scientific problems like, for example, text parsing, and on the buisness ground, like use of Django or Rails for creating web applications.
The state of Plone
short talk presented by Maciej Dziergwa about current Plone situation - based on Matt Hamilton's PloneConf2009 talk. After the talk we had a short discussion about current situation of Polish Plone Community. Plone is still not popular in Poland as it is in Italy...
Compiled Websites with Plone, Django and SSI
very interesting talk by Łukasz Langa and Wojciech Lichota about Plone, Django and SSI deployment. Using stxnext.staticdeployment you can deploy Plone site to static files. You can add dynamic stuff (like commenting) using Django. Finally you can glue everything together using Apache SSI mod_include. If you need search engine you can use and integrate, everything what I've mentioned before, with Xapian (or Solr).
You can find slides here.
Caching techniques in Python
some interesting caching techniques explained by Michał Domański and Michał Chruszcz. In Plone world we already know plone.memoize - a decorator for caching the values of functions and methods. You can use it of course outside Zope/Plone environment. If you need something more - check out i.e. pylibmc. At the end they've covered also reverse proxy with Varnish.
Oct 16, 2009
Fast content import
For one of our customers we have implemented a prototype for fast importing data to Plone. Instead of creating thousands of Archetype-based objects - we are creating only brains. Real objects will be created manually by users. The difference is huge.
The task was simple - import to Plone 36.000 documents (with all children it gives the total of 120.000 objects). Simply creating it using invokeFactory will take too much time (aprox. 14 hours). Why not create just brains and let users decide which document fully migrate? This is what we did.
We started with import script which creates brains in portal_catalog using directly catalog_object method:
pc = getToolByName(self.context, 'portal_catalog')
pc.catalog_object(dummy_object, dummy_object.path)
dummy_object is a simple python object with all metadata that we need later for portal_catalog query:
>>> pp dummy_object.__dict__
{'title': u'dummy title',
'id': u'simple_id',
'review_state': 'private',
'path': '/plone/importfolder/ToBeMigrated_simple_id'}
After lunching the script (it took 19 minutes) we had all the brains (36.000) in portal_catalog with proper metadata/index updated. Now we need to allow users to see them. So we created traverser for our importfolder:
def __bobo_traverse__(self, REQUEST, name):
if name.startswith('ToBeMigrated'):
view = getMultiAdapter((self, self.REQUEST), name='to_be_migrated')
view.setBrainId(name)
return view
return super(ImportFolder, self).__bobo_traverse__(REQUEST, name)
which returns a simple BrowserView with the brain.id. The view has a template which informs end-user that this document need to be migrated. If he decided to import it - system will start import process for selected brain.id.
The rest is pure Plone folder_contents view which lists my 'dummy' brains in import_folder (cause the path in the brain is correct). Simple and much faster ;-)
Sep 24, 2009
How to revive an unstartable Plone 3.2.2 under windows XP Pro SP3
You may have experienced erratic behaviour from installations of Plone under Windows XP. This contribution, based on my personal experience and on what I found searching the web, will hopefully let you fix a Zope service that become unstartable without any apparent reason, or at least find a workaround by running runzope.bat from the command line.
In mid-september 2009 I downloaded and installed successfully the Plone 3.2.2 bundle for windows, including Python and Zope 2.something (you already understood that I am not an expert in the field).
Plone worked fine, I customized my local installation (to be used for demo purposes) without any problem.
After two days without using Plone (that I usually started from the "Plone Controller" application) I found that the "Plone Controller" could not start anymore the Zope instance. The Zope instance service - even though marked for automatic start - could not be started, the windows system log messages were useless (error 01x, no explanation).
In similar situations, usually Zope may be started by runzope.bat from the command line: I tried that workaround that proved effective, even though I did not engage in a full set of site update and configuration: some posts in technical fora suggest that this solution does not necessarily provide a fully working Zope / Plone instance.
Not fully satisfied with the workaround, I explored the Web for solutions, and here is what I found and applied successfully (ZI = Zope instance, PC = Plone Controller, RZ = Runzope.bat). All the paths are the default paths resulting from a default run of the Plone Win 32 bit installer. Here is a sequence of all the steps, problem and solution.
- ZI could not be started by PC - issues error message in endless cascading pop-ups
- Plone local site (in my case, http://localhost:8080/PloneCesare) is obviously inaccessible
- At this stage, ZI *could* be manually started by RZ, issuing from the command line:
C:\Programmi\Plone\parts\instance\bin\runzope.bat
- Plone local site http://localhost:8080/PloneCesare now is accessible, but PC is not aware that ZI is started, as long as PC "sees" only the Zope service, not the manually started instance
- Zope Instance service (default name:"Zope instance at C:\Programmi\Plone\parts\instance") remains unstartable. Furthermore, it does not seem to retain the parameters set from the Windows "Services" interface.
-
To solve the issue, I reset the service options, by issuing from the command line:
C:\Programmi\Plone\python\python.exe C:\Programmi\Plone\parts\instance\bin\zopeservice.py --startup auto install
The execution returns the following lines:
Installing service Zope_78966557 Changing service configuration Service updated
C:\Programmi\Plone\python\python.exe C:\Programmi\Plone\parts\instance\bin\zopeservice.py start
Starting service Zope_78966557
Please note that most of the information available on the Web about similar issues refers to older Plone versions, and may not apply to the newest releases. Please note also that Win XP Home may behave in a different way.
Sep 06, 2009
Pydev 1.5.0: into the wild
Il papà di Pydev annuncia il rilascio della versione 1.5.0 di questo eccezionale plugin per eclipse. La novità principale è che per la prima volta sarà completamente open source!
Da anni Pydev è uno degli strumenti favoriti da una moltitudine di sviluppatori Python per merito della sua completezza.
Fino a poco tempo fa al plugin open source Pydev si affiancava Pydev Extensions, liberamente scaricabile ma a codice chiuso. Dall'ultima versione, la 1.5.0, Pydev e Pydev Extensions sono stati unificati in un unico progetto open source! La notizia è stata data in questo annuncio da Fabio Zadrozny, lo sviluppatore che ha ideato questo gioiello.
Il link per l'installazione tramite eclipse è: http://pydev.org/updates
N.B.: occorre rimuovere eventuali versioni precedenti di Pydev prima di procedere all'aggiornamento.
Non possiamo che apprezzare Aptana, la società che finanzia lo sviluppo di Pydev, per questa scelta! Se nell'immediato si limita a togliere a molti sviluppatori il fastidio di chiudere una finestra promozionale. che compare periodicamente mentre si utilizza eclipse, nel lungo periodo permetterà a questo plugin di crescere con maggiore rapidità e di conquistare sempre più utenti.
Riferimenti:
- Il link della notizia originale
- La home page di Pydev
- La home page di Aptana
- Link per aggiornare eclipse: http://pydev.org/updates

