Friday, February 26, 2010

Monday, February 22, 2010

plone.recipe.pound Error: Bad version 1.7

While installing pound in a Plone buildout, an error occurred:
The version, 1.7, is not consistent with the requirement, 'Markdown>=2.0.1'. 
While:
Installing.
Getting section poundbuild.
Initializing section poundbuild.
Installing recipe plone.recipe.pound.
Error: Bad version 1.7

Adding
[versions]
Markdown = 2.0.3
to the buildout remedies this. Funny it can't do it by itself.

Friday, February 19, 2010

A Plone 4 buildout setup

A set of buildout files for Plone 4. My goal is to cover the entire project. from a development setup to production.

buildout-base.cfg



Define here everything you want to have in your portal that is not in standard Plone.


[buildout]
extends =
buildout-plone.cfg
# ...

[instance]
eggs +=
# ...
# eggs for your site



buildout-plone.cfg



A default Plone buildout. This one was created with paster create -t plone3_buildout and uses Plone 4.0a4.


[buildout]
parts =
productdistros
instance
zopepy

# Change the number here to change the version of Plone being used
extends =
http://download.zope.org/Zope2/index/2.12.3/versions.cfg
http://dist.plone.org/release/4.0a4/versions.cfg
versions = versions


# Add additional egg download sources here. dist.plone.org contains archives
# of Plone packages.
find-links =
http://dist.plone.org/release/4.0a4
http://dist.plone.org/thirdparty

# Add additional eggs here
eggs =

# Reference any eggs you are developing here, one per line
# e.g.: develop = src/my.package
develop =





# Use this section to download additional old-style products.
# List any number of URLs for product tarballs under URLs (separate
# with whitespace, or break over several lines, with subsequent lines
# indented). If any archives contain several products inside a top-level
# directory, list the archive file name (i.e. the last part of the URL,
# normally with a .tar.gz suffix or similar) under 'nested-packages'.
# If any archives extract to a product directory with a version suffix, list
# the archive name under 'version-suffix-packages'.
[productdistros]
# For more information on this step and configuration options see:
# http://pypi.python.org/pypi/plone.recipe.distros
recipe = plone.recipe.distros
urls =
nested-packages =
version-suffix-packages =

[instance]
# For more information on this step and configuration options see:
# http://pypi.python.org/pypi/plone.recipe.zope2instance
recipe = plone.recipe.zope2instance
user = admin:admin
http-address = 8080
#debug-mode = on
#verbose-security = on
blob-storage = var/blobstorage
# If you want Zope to know about any additional eggs, list them here.
# This should include any development eggs you listed in develop-eggs above,
# e.g. eggs = Plone my.package
eggs =
Zope2
Plone
${buildout:eggs}

# If you want to register ZCML slugs for any packages, list them here.
# e.g. zcml = my.package my.other.package
zcml =

products =
${buildout:directory}/products
${productdistros:location}

[zopepy]
# For more information on this step and configuration options see:
# http://pypi.python.org/pypi/zc.recipe.egg
recipe = zc.recipe.egg
eggs = ${instance:eggs}
interpreter = zopepy
scripts = zopepy


buildout-dvl.cfg



A buildout for local development. This uses mr.developer to develop eggs, and adds dev products (such as plone.reload), testrunner and omelette.


[buildout]
extends =
buildout-base.cfg

extensions = mr.developer
sources = sources
auto-checkout +=
# ...
parts +=
test
omelette
unzip = true

[omelette]
recipe = collective.recipe.omelette
eggs = ${instance:eggs}
packages = ${instance:location}/lib/python ./

[sources]
# ...

[instance]
debug-mode = on
verbose-security = on
eggs +=
plone.reload
Products.Clouseau

[test]
recipe = zc.recipe.testrunner
eggs =
${instance:eggs}



buildout-tst.cfg



The test server (as in testing / acceptance / production). This adds zeo config to buildout-dvl.cfg. (My tst/acc/prd setup consists of two machines, each of them runs one client.)

The zeo settings are read from another file, to keep passwords out of version control.


[buildout]
extends =
buildout-dvl.cfg
zeo.cfg
test-settings.cfg




zeo.cfg



Turns a single instance buildout into a zeo server-client setup.


[buildout]
extends = buildout-base.cfg

parts +=
zeoserver
client1

[zeoserver]
recipe = plone.recipe.zeoserver

[client1]
recipe = plone.recipe.zope2instance
debug-mode = ${instance:debug-mode}
verbose-security = ${instance:verbose-security}
eggs = ${instance:eggs}
zcml = ${instance:zcml}
products = ${instance:products}
zeo-client = on
# Note: Do not set shared-blob = on with multiple machines.


test-settings.cfg



An example for the settings required by buildout-tst.cfg.


[zeoserver]
zeo-address = 18105
file-storage = /ha-data/APPS/viva/tst/filestorage/Data.fs
# use full path for blob-storage
blob-storage = /ha-data/APPS/viva/tst/blobstorage

[client1]
user = admin:secret
http-address = 8085
zeo-address = x.x.x.x:18085



buildout-dvl-zeo.cfg



A local development buildout which uses zeo setup with two clients.


[buildout]
extends = buildout-dvl.cfg

parts +=
zeoserver
client1
client2

[zeoserver]
recipe = plone.recipe.zeoserver
zeo-address = 8100

[client1]
recipe = plone.recipe.zope2instance
user = ${instance:user}
debug-mode = ${instance:debug-mode}
verbose-security = ${instance:verbose-security}
eggs = ${instance:eggs}
zcml = ${instance:zcml}
products = ${instance:products}
zeo-client = on
zeo-address = ${zeoserver:zeo-address}
http-address = 8080

[client2]
<= client1
http-address = 8081

Monday, February 15, 2010

Copying input from one terminal another

There's a couple of solutions for copying input from one terminal to several others. I used to use Konsole, which has two drawbacks:
* You have to setup which terminal you copy to every time you start it;
* It pulls in all kinds of KDE dependencies, which bothers me because i have Gnome.

I now use ClusterSSH as an alternative to Konsole. Its advantages are:
* Being able to define a setup, so all you have to type is cssh {setup}
* Having a separate window for the stuff that gets put in all terminals, so it's clear immediately what goes where, immensely reducing the amount of confusion and errorst
* It's lightweight

Its main disadvantage is that it always starts an ssh session, so now i'm ssh-ing to my localhost sometimes. Another thing is that the setup file is in /etc/ by default, requiring root permissions to modify it. But it's still my tool of choice.

Sunday, February 14, 2010

French phonetic characters

As a student of the French language, which i am not, one is sometimes required to analyze French phonology. In the course of this, one might want to write about one's work, and inserting symbols in documents on a computer becomes a necessity.

To cut this short, the question is: How do you type a "backwards c with a tilde on it"?

A paragraph or two about OpenOffice first. OpenOffice comes with a huge list of special characters, which you can insert (by clicking "Insert" > "Special character", funnily enough). A list of characters and symbols appears, which you can just click to insert. There's a "subset" of characters called IPA Extensions, IPA stands for International Phonetic Alphabet.

Having this wealth to choose from is nice, but to speed up typing it would be nice not have to use the mouse each time. Luckiliy, there are shortcut keys. In the lower right corner, you will see something like "U+00A9 (169)" (example for the copyright symbol). The first string, the one after the 'U+', is the Unicode "code point", an internationally valid code which represents the character. The second one, between the brackets, is the Latin-1 code, another code representation for the character. Remember that in the old days, we used to type Alt+{number} to insert special characters. Latin-1 is a simple character encoding which contains enough characters for most Western languages, but cannot be used for something as complex as phonetic characters.

On Ubuntu, you can create a character from its Unicode code point with Ctrl+Shift+u {codepoint}. (Windows?) This will work not only in OpenOffice.org, but in many programs where you can enter text. For example, if i hold down Ctrl and Shift and press 'u', an underlined 'u' appears. I then enter '0254' and press Enter, and what do i get? A beautiful reversed c!


ɔ


The question remains how to create the tilde on my "backward c". It turns out there's also character subsets called "Spacing modifying letters" and "Combining diacritical marks". The characters from the latter subset will add themselves to the previous character when clicked. You can look up these characters in OpenOffice, but they're available on lots of places. Unicode Phonetic Symbols is a good starting point. After some searching around, it turns out the code for the tilde is 0303. So first i create my reversed c (Ctrl+U 0254 Enter), and then the tilde (Ctrl+U 0303 Enter), and the tilde places itself above the reversed c.


ɔ̃


Friday, February 12, 2010

Turning my Plone 4 buildout into a ZEO server/client setup

This post has been replaced with this one

Using zc.recipe.testrunner with Plone 4

To test the contentratings package on a Plone 4.0a4 buildout, i added this to my buildout:
[test]
recipe = zc.recipe.testrunner
eggs =
${instance:eggs}
contentratings

Wednesday, February 10, 2010

Making SVN ignore certain files

To ignore the files *.po.backup and .registration.cache in my i18n folder, i ran: svn propedit svn:ignore i18n/. This opened an editor where i added these files, one per line:
*.po.backup
.registration.cache

Makefile for generating translation files in i18n folder

# Makefile for creating translation files (.pot and .po) in Plone products.
# Kees Hink, 2009-2010
#
# Place this inside the 'i18n' directory in your package.
# Adjust the definitions.
# When you run 'make', a .pot file will be created.
# Run 'make xx-translation' to create a translation file for language xx.

# Definitions
DOMAIN = 'Products.MyProduct'
# The definitions below are derived from the definitions above.
# You could also override them.
GENERATED := ${DOMAIN}-generated.pot
MANUAL := ${DOMAIN}-manual.pot
POTFILE := ${DOMAIN}.pot

default: generate merge

generate:
@echo "Extracting strings from templates, putting them in generated potfile"
i18ndude rebuild-pot --pot ${GENERATED} --create ${DOMAIN} ../

merge:
@echo "Merging generated and manual string files into potfile"
i18ndude merge --pot ${POTFILE} --merge ${MANUAL} --merge2 ${GENERATED}

%-translation:
@echo "Making backup of translation file"
if [ ! -e ${DOMAIN}-$*.po ]; \
then touch ${DOMAIN}-$*.po;\
else cp ${DOMAIN}-$*.po ${DOMAIN}-$*.po.backup;\
fi
@echo "Syncing translation file"
i18ndude sync --pot ${POTFILE} ${DOMAIN}-$*.po


Beware:
* Makefiles are always indented with tabs
* You may require a space at the end of a line after a backslash

Wednesday, February 3, 2010

Using the locate command with --regex (or --regexp)

locate is much faster than find...

# Find images in my homedir and its descendants (children, thier children etc.)
locate --regex \/home\/kees\/.*\(.png\|.jpg\|.gif\)
# Find images only in direct children of my homedir
locate --regex \/home\/kees\/[^\/]*\/[^\/]*\(.png\|.jpg\|.gif\)

Tuesday, February 2, 2010

Favoriete Nederlandse scheldwoorden

Aangestoken door een lijstje met iemands favoriete Franse scheldwoorden, dat
echt te makkelijk en te grof was, hier mijn top-N:


  • Boefje

  • Druif

  • Muppet

  • Schelm

  • Schobbejak

  • Schavuit

  • Zoon van een coyote met een gele lever

  • Boerenlul

  • Idioot

  • Schertsfiguur



Bij "Boerenlul" moet ik altijd denken aan het verhaal van een voetballer in Zuid-Oost Drenthe die van het veld gestuurd werd omdat hij "boetnspul" (buitenspel) naar de scheidsrechter riep. De scheids was helaas minder bekend met het dialect en verstond het verkeerd.

"Boefje" is leuk om vooral niet te gebruiken voor kinderen (brugklassers die te laat komen en zo), maar voor witteboordencriminelen die voor miljoenen oplichten. Een duchtige schrobbering voor hen!

"Idioot" brengt die 80'er jaren-melancholie met zich mee van Murdoch, der richtige Vollidiot.

Schelm, Schobbejak en Schavuit is een heilige 3-eenheid. Max und Moritz in de Nederlandse vertaling.

Exemplarisch voor het Creatieve Schelden is "Zoon van een coyote met een gele lever". De collega die mij hiervoor uitmaakte kan er zo nog 10 uit zijn mouw schudden. Doet me denken aan de vloek: "May your daughter marry a jazz musician" (Zappa?).

Ook bij "Schertsfiguur" is een voetbalverhaal: Een speler die bij een Europese wedstrijd voor een Russische (meen ik) club uitkwam, was kermend van de pijn op de grond blijven liggen, zodat de commentator zich afvroeg hoe lang het zou duren voordat de bal over de zijlijn zou worden gespeeld. Toen er even later een bal de kant van de speler op kwam, stond hij ineens op en rende als een kievit. De commentator had zich in de luren had laten leggen en alleen dit woord, vol walging uitgesproken, leek zijn afkeuring te kunnen bevatten.

Ohja, in de categorie eervolle vermelding (met dank aan het internet): Addergebroed, Butje (Gr.), Fabricagefout, Gek, Hansworst, Minkukel, Mispunt, Oliebol, Quasimodo, Slampamper, Slapjanus, Stuk verdriet, Uilskuiken, Worm, Zak hooi.

Monday, February 1, 2010

Fixing PosKey Errors in Zope

Update: For a possibly easier way to _find_ PosKey errors, look here: http://www.zopyx.de/blog/checking-your-zodb-storages-for-poskey-errors

Some objects in my Plone site were broken: when clearing and rebuilding the catalog, i saw "PosKey" errors in my Zope logfile (*). Which objects are broken, and what to do about it?

I put a pdb statement in the file which caused errors, which was CMFCore/CatalogTool.py, line 390:

+ try:
+ dummy = base_hasattr(obj, 'indexObject')
+ except:
+ import pdb; pdb.set_trace()

I re-ran the catalog rebuild and was dropped into a pdb shell:

> from Acquisition import aq_parent
> parent = aq_parent(obj)

This showed which folderish thing contained the broken object.

Stopping the pdb session (using c, continue with the program) and looking in the ZMI, i was able to see that these objects were indeed broken: They could not be viewed in the ZMI (the same PosKey error).

Luckily, you can start Zope in debug mode for this, so it's Zope debug to the rescue:

$ ./client0/bin/zopectl debug # yep, a Plone 2.5 site
> site = getattr(app, 'my-sites-id-in-zope')
> folder = site.somefolder
> delattr(folder,'my-broken-object')
> import transaction; transaction.commit()


Broken object is thrown away: Problem solved. You can now clear and rebuild the catalog, and there will be much rejoicing.

If something in your site depends in the object being there, most likely with a special id, you could re-create the object from the Zope debug console like this:

> from Products.SomeProduct.content.SomeContentType import SomeContentType
> id = 'special-id' # use an id that's unique in the folder
> recreated_object = SomeContentType(id)
> folder.special-id = recreated_object
> import transaction; transaction.commit()


(*) The question remains, how object get "broken" in this manner. Anyone willing to shed light on this is very welcome to reply.