Personal tools

December

Dec 18, 2009

"./bin/buildout" senza "-N" su Plone 3.1? Ahi!

Vediamo di spiegare quello che succede a tantissimi quando provano ad aggiornare il loro vecchio Plone 3.1

Prima di tutto: "-N" è vostro amico!

I problemi li vediamo sotto, ma ricordate che l'opzione -N su un vecchio Plone come può essere la versione 3.1 è un parametro vivamente consigliato!

Volete installare un nuovo prodotto?
Ricordate che "-N" sta per non-updating, quindi solo gli egg già scaricati non vengono aggiornati, ma se la vostra modifica all'istallazione richiede la presenza di un nuovo modulo, questo viene normalmente prelevato (...e speriamo che la versione scaricata sia compatibile... in caso contrario, cercatene una che lo sia! vedere sotto...).

Di chi è la colpa?

I problemi sono iniziati con qualche prodotto rilasciato nell'era Plone 3.3, ma la cosa è diventata particolarmente sensibile (e fastidiosa) col rilascio delle prime versioni egghizzate di Plone 4.

Plone 3.1 non aveva le versioni degli egg fissate dai file versions (e.g: http://dist.plone.org/release/3.3.1/versions.cfg per Plone 3.3.1).

Per di piu "Plone" e "Zope2" sono diventati "veri" egg da poco.

Iniziano quindi ad essere disponibili molti egg che (giustamente) richiedono dipendenze da questi moduli software...

...peccato che a loro volta questi abbiano dipendenze verso altri egg che sono troppo aggiornati per la vecchia versione di Plone 3.1.

NB: l'idea non è sbagliata di per se! In un mondo perfetto se un utente che non sa nulla di Zope & Plone naviga la rete e trova il riferimento ad un prodotto che si chiama Ploneboard e che fornisce un forum, potrebbe volerlo provare. Se tenta di installarlo con easy_install, perché questo non dovrebbe a sua volta scaricarmi un ambiente Plone completo?

Vediamo di risolvere

Diciamo che state leggendo questo perché vi siete dimenticati di tenere l'opzione "-N", oppure un nuovo prodotto che dovete per forza installare ha delle dipendenze pericolose, o siete masochisti...

Ad ogni modo (i gusti son gusti) eccovi un esempio di un buildout di un Plone 3.1 che di recente mi ha dato problemi.

[buildout]
parts =
    plone
    zope2
    instance
    zopepy
    fss

# Add additional egg download sources here. dist.plone.org contains archives
# of Plone packages.
find-links =
    http://dist.plone.org
    http://download.zope.org/ppix/
    http://download.zope.org/distribution/
    http://effbot.org/downloads

# Add additional eggs here
# elementtree is required by Plone
eggs =
    elementtree
    iw.fss>=2.7.5,<2.7.6dev
    iw.recipe.fss
    Products.DocFinderTab
    
# Reference any eggs you are developing here, one per line
# e.g.: develop = src/my.package
develop =
    ...

[plone]
recipe = plone.recipe.plone

[zope2]
recipe = plone.recipe.zope2install
url = ${plone:zope2-url}

[instance]
recipe = plone.recipe.zope2instance
zope2-location = ${zope2:location}
user = admin:admin
http-address = 7084
#debug-mode = on
#verbose-security = on
effective-user = plone

eggs =
    ${buildout:eggs}
    ${plone:eggs}
    ...

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

products =
    ${buildout:directory}/products
    ${plone:products}

[zopepy]
recipe = zc.recipe.egg
eggs = ${instance:eggs}
interpreter = zopepy
extra-paths = ${zope2:location}/lib/python
scripts = zopepy

[fss]
recipe = iw.recipe.fss
storages =
    ...

Trovate degli omissis per alcune parti generiche e non interessanti.

Qual'è l'effetto di lanciare un buildout con questo .cfg, tenendo conto delle recenti dipendenze degli egg con Plone e Zope2?
Una frittata... e non particolarmente piacevole.

Ecco cosa potreste leggere a console (usate l'opzione "-v" per individuare gli errori):

...
Installing 'plone.recipe.zope2instance'.
We have the best distribution that satisfies 'plone.recipe.zope2instance'.
Picked: plone.recipe.zope2instance = 4.0a2
Getting required 'Zope2>=2.12.1'
  required by plone.recipe.zope2instance 4.0a2.
We have no distributions for Zope2 that satisfies 'Zope2>=2.12.1'.
...

In pratica, l'aggiornamento prova a scarica l'ultima versione di plone.recipe.zope2instance, ma dall'uscita di Plone 4 l'ultima versione risulta essere la 4.0a2. Questo va già male di per se, ma come accennato sopra un altro grosso problema è che questo è dipendente dall'egg Zope2 versione 2.12.1.
Inutile proseguire oltre; a sua volta questo egg ha un'infinità di altre dipendenze... vediamo dove porta tutto questo:

Getting distribution for 'Zope2>=2.12.1'.
Running easy_install:
/opt/local/bin/python "-c" "from setuptools.command.easy_install import main; main()" "-mUNxd" "/Users/luca/Library/Buildout/eggs/tmpFz8U_N" "-q" "/Users/luca/Library/Buildout/downloads/dist/Zope2-2.12.1.tar.gz"
path=/Users/luca/Library/Buildout/eggs/setuptools-0.6c11-py2.4.egg

src/initgroups/_initgroups.c: In function ‘initgroups_initgroups’:
src/initgroups/_initgroups.c:34: warning: implicit declaration of function ‘initgroups’
  File "build/bdist.macosx-10.6-i386/egg/Zope2/Startup/zopectl.py", line 313
    finally:
          ^
SyntaxError: invalid syntax
  File "/Users/luca/Library/Buildout/eggs/tmpFz8U_N/Zope2-2.12.1-py2.4-macosx-10.6-i386.egg/Zope2/Startup/zopectl.py", line 313
    finally:
          ^
SyntaxError: invalid syntax
While:
  Installing.
  Getting section instance.
  Initializing section instance.
  Installing recipe plone.recipe.zope2instance.
  Getting distribution for 'Zope2>=2.12.1'.
Error: Couldn't install: Zope2 2.12.1

Questo non è l'unico errore possibile, ma spieghiamolo: Plone 4 userà Python 2.6 e la sintassi non è completamente compatibile con Python 2.4 usato fino alla versione 3.3.

In altri casi invece il problema è un conflitto di dipendenze: ad esempio Plone 3.1 ha già un egg Zope2, la cui versione è la 0.0.

Questo perché nei buildout di Plone vengono usati (e possono essere usati anche per i vostri scopi) i fake-eggs. Un fake egg non è un vero e proprio egg ma il buildout crede di averlo disponibile alla versione (di solito) 0.0.

In un modo o nell'altro, il buildout non arriva a conclusione...

Come risolvere

La prima regola è analizzare gli errori; lanciare quindi il buildout con l'opzione "-v" per avere messaggi dettagliati, poi risalire la catena delle dipendenze nella console e trovare chi tra questi egg sta scaricando "Zope2>2.12.1" (oppure altri egg non appropriati perché rilasciati per Plone 4).

Nell'esempio sopra il problema era plone.recipe.zope2instance. Ci possono essere altri egg maledetti (ne vediamo almeno un altro più avanti) a seconda dei prodotti usati nel vostro buildout.

La soluzione è fissare le versioni:

[buildout]
parts =
    plone
    zope2
    instance
    zopepy
    fss

versions=versions

# Add additional egg download sources here. dist.plone.org contains archives
# of Plone packages.
find-links =
    http://dist.plone.org
    http://download.zope.org/ppix/
    http://download.zope.org/distribution/
    http://effbot.org/downloads

# Add additional eggs here
# elementtree is required by Plone
eggs =
    elementtree
    iw.fss>=2.7.5,<2.7.6dev
    iw.recipe.fss
    Products.DocFinderTab
    
# Reference any eggs you are developing here, one per line
# e.g.: develop = src/my.package
develop =
    ...

[versions]
plone.recipe.zope2instance = 3.6
...

La nuova parte versions, usata esplicitamente nella parte buildout, fissa plone.recipe.zope2instance alla "vecchia" versione 3.6.
Non ho una regola per trovare la versione giusta... andare alla pagina del Cheeseshop e guardare la sezione CHANGES di questo egg è stato sufficiente. La 3.6 è la main release precedente alla 4.0.

Questo potrebbe essere sufficiente... in presenza di altri egg velenosi si può ricorrere all'uso esplicito degli additional-fake-eggs.

Alcuni egg ad esempio hanno una dipendenza da "Plone" (la cui vita come egg, ricordo, è iniziata con la versione 3.2).

Ecco come modificare la parte zope2 per sistemare la dipendenza a Plone:

[zope2]
recipe = plone.recipe.zope2install
url = ${plone:zope2-url}
fake-zope-eggs = true
additional-fake-eggs =
    Plone

In questo modo il nostro buildout avrà già disponibile un egg "Plone" alla versione 0.0.

I problemi rimangono in vari casi. Cosa succedere ad esempio se voglio usare une prodotto che ha una dipendenza ad una versione precisa di un egg che ho nella sezione fake-eggs? Ad esempio: Ploneboard versione 2.1beta2 ha una sezione di dipendenze così fatta (preso dal suo setup.py):

      install_requires=[
        'setuptools',
        'Products.SimpleAttachment',
        'plone.app.controlpanel',
        'plone.app.portlets',
        'plone.portlets',
        'plone.memoize',
        'plone.i18n',
        'python-dateutil',
        'Plone >= 3.3',
      ],

Anche lanciando il nostro buildout con opzione "-N" e con la presenza del fake-egg "Plone", buildout prova giustamente ad ottenere una versione di "Plone>= 3.3". La versione 0.0 ovviamente non va bene.

La sezione fake-eggs ha una potenzialità maggiore; potrei cambiare il buildout così:

[zope2]
recipe = plone.recipe.zope2install
url = ${plone:zope2-url}
fake-zope-eggs = true
additional-fake-eggs =
    Plone=3.3

Questo significa che il nostro fake-egg "Plone" non sarà più a versione 0.0

NB: ovviamente non è detto (e non ho testato) che provare questa versione di Ploneboard, fatta per Plone 3.3 su un Plone 3.1, porti a qualche risultato funzionante... spero che passi il concetto generale dell'esempio!

Un ulteriore esempio

Ora voglio anche usare in questo vecchio buildout un file .cfg per lo sviluppatore, magari copiato da altri buildout. Questo aggiunge alcuni egg molto utili per lo sviluppo in locale:

[buildout]
extends = buildout.cfg

parts+=
    omelette

[instance]
http-address = 8080
eggs +=
    plone.reload==1.1

zcml +=
    plone.reload

[omelette]
recipe = collective.recipe.omelette
eggs =
    ${instance:eggs}

products =
    ${instance:products}

Se lancio il buildout senza l'opzione "-N" torno ad avere problemi:

./bin/buildout -vc sviluppo.cfg

Ottengo questo:

While:
  Installing instance.
Error: There is a version conflict.
We already have: Zope2 0.0
but Products.CMFCore 2.2.0-beta requires 'Zope2>=2.12.0b4dev'.

Come abbiamo già fatto: chi è che sta provando a scaricare Products.CMFCore 2.2.0-beta (anche CMF non era egghizzato fino a poco tempo fa)?

Analizzando indietro il trace, troviamo che il cattivo è plone.reload:

Getting required 'Products.CMFCore'
  required by plone.reload 1.1.
We have the best distribution that satisfies 'Products.CMFCore'.
Picked: Products.CMFCore = 2.2.0-beta

Possiamo di nuovo superare la cosa tramite fake-eggs, oppure fissando la versione di plore.reload ad una versione più vecchia, compatibile con Plone 3.1.

Nel primo caso modifico buildout.cfg di nuovo, come segue:

additional-fake-eggs =
    Products.CMFCore 
    Plone=3.3

Anche in questo caso forse sto barando... ma non è detto (vedere sotto).

Il modo canonico è come sempre trovare una versione compatibile; rimuovo il fake-egg "Products.CMFCore" e questa volta modifico sviluppo.cfg:

[instance]
http-address = 8080
eggs +=
    plone.reload<1.1dev

E con questo abbiamo finito!

Quale modo è il migliore?

In generale, fissare le versioni è la giusta soluzione, e con l'uso di versions si sta facendo quello che le release successive di Plone hanno fatto.

L'uso dei fake-eggs è comunque una scappatoia da non dimenticare... Magari Ploneboard 2.1 funziona anche con Plone 3.1... solo che nessuno lo ha mai testato (e potreste volerlo fare voi).

Lo stesso per plone.reload. La versione successiva (la 1.2) ha rimosso la dipendenza all'egg Products.CMFCore. Magari anche la 1.1 funziona correttamente con il nostro vecchio Plone e gli sviluppatori si sono accorti di come questa dipendenza creasse più problemi che altro.

Dec 14, 2009

collective.flowplayer_toolbar: adding accessibility in an unobtrusive way

The way I used to make Flowplayer use inside Plone a little more accessible, this time without branching the collective.flowplayer product!

First of all: some terms

After finishing this article I understand that people not familiar with this argument and software can be confused, so:

  • Flowplayer (in capitalized form) is a Flash player for audio/video files, indipendent from the Plone technology.
  • collective.flowplayer is a Plone products that use Flowplayer and give this player well integrated in Plone CMS
  • collective.flowplayer 1.x is an old release family, that use Flowplayer 2.x
  • collective.flowplayer 3.x is the last release family, that use Flowplayer 3

Introduction to main characters

Flowplayer is one of the most promising Flash audio/video player available right now, and we can use it in a simple way inside Plone site thanks the collective.flowplayer, a well know product that replaced the use of p4a.video in recent Plone experiences.

Flowplayer is good, and open source, but not the most accessible available player. Our work with collective.flowplayer accessibility begin when the available release was the 1.0.x version.

As noted above, Flowplayer version used in this old release was the old 2.x, so many of the most recent and cool features were missing; on the other hand, the current 3.x family is heavily integrated with jQuery Javascript framework.
Not less important, the Flowplayer team is the one who released the jQuery Tools, the javascript addon for jQuery recently integrated in Plone 4 thanks to plone.app.jquery.

Fixing collective.flowplayer 1.x

The main accessibility problem of Flowplayer is its flash controlbar. Practical tests show that is not easy to handle video controls using the keyboard.

Our customer, the same that ask for accessible videos in Plone and also like Flowplayer very much, provide us a static HTML example of Flowplayer that use Javascript controlbar, simply usable with keyboard. The problem was that this example supports Flowplayer 3.2, the current version of the Flash player, but not the version used in the Plone addon.
Also the example provide a patched version of the controlbar plugin for Flowplayer. This custom version add some missing HTML attributes and WAI-ARIA support.

After looking on the web we found that even if Flowplayer 2 was backward compared to the new branch, it provides some limited APIs, usable through Javascript.

Our target was to replicate all the feature seen in the Flowplayer 3 demo in the Flowplayer 2 environment... of course this was not so easy! However after some work we find a way to provide those features:

  • a play/pause button
  • a stop button (not required, but was simple to do)
  • a timer display

The collective.flowplayer branchThe only feature "impossible" to obtain (directly) was the progressbar... to be honest, some additional Javascript could also realize this (we have the duration of the video, we have the current execution time, we know how to perform arithmetic division... why not draw ourself? :-) but was enough.

What we really don't like was this: we found no (simple) way to write a Plone addon that work with collective.flowplayer 1.0, adding to it our new features.

We don't waste more time: we made a branch of the original collective.flowplayer 1.x, providing our new feature.

Thank you! Thank you! We have collective.flowplayer 3.x!

After a few weeks collective.flowplayer 3.x was released (I think that the developers team skipped the 2.x version for aligning the Plone product's version to the Flowplayer one).
So we came back to the original example give to us (the customer project was happy finished using our branch) just for test the new feature available and to understand is in future a new, better approach is possible.

The API's of the latest Flowplayer versions are more complete and powerful, heavily filled with the jQuery power.

This time we were able to develop something that could live and enhance the original collective.flowplayer, releasing only a new product: collective.flowplayer_toolbar.

The final result really better than the old approach; without embarrassment I can say that we did a few line of codes! The most part of the work of our new controlbar came from Flowplayer features and one more time from the great jQuery library.

You want see the "core" of this product?

/**
 * Javascript code for adding accessible toolbar to flowplayer players in the page 
 */

jq(document).ready(function(event) {
	$f("*").each(function() {
		this.onLoad(function(event) {
			this.getPlugin("controls").hide();
			var p = jq(this.getParent());
			var p_width = p.width();
			var time_width = (p_width<400?99:129);
			var hulu_id = "hulu-"+ (jq(".hulu").length+1);
			p.after('<div id="'+hulu_id+'" style="width:'+p_width+'px" class="hulu">\n'
				+'<a class="play" href="javascript:;" role="button">Play</a>\n'
				+'<div class="track" style="width:'+(p_width-46-46-time_width)+'px">\n'
				+'    <div class="buffer"></div>\n'
				+'    <div class="progress"></div>\n'
				+'    <div class="playhead"></div>\n'
				+'</div>\n'
				+'<div class="time" style="width:'+time_width+'px"></div>\n'
				+'<a class="mute" href="javascript:;" role="button">Mute</a>\n'
				+'</div>\n');
			this.controls(hulu_id);
			// Now I'll fix all other positions of the new toolbar
			jq("#"+hulu_id+" a.mute").css('left', p_width-46);
			jq("#"+hulu_id+" div.time").css('left', p_width-46-time_width);
		});
	});
});

The rest of the egg simply use a limited version of the original CSS of the demo page in Flowplayer site, the patched controlbar plugin (but you can use the original one without problems)... nothing more!

The jQuery presence make real the injection our new feature on existings Flowplayer instance in the page (for example, this is also working properly for our redturtle.video product). No need to patch/branch collective.flowplayer, also no need to override some views or resource of it.

Conclusion

This work can be also a proof-of-concept for future Flowplayer integration with additional features. The player supports many additional plugins (Yuri point my attention to the Caption Flash plugin...).

Dec 03, 2009

2010 Content Technology Vendor Map

by fabio
Filed Under:

cms vendor map

Full report available here