Skip to content. | Skip to navigation

Personal tools
Sections
You are here: Home Topics english
Navigation
 

english

Mar 16, 2010

PloneboardNotify: how tests will save my fat boy

by Luca Fabbri — last modified Mar 16, 2010 09:04 AM

A new release of PloneboardNotify... no much more features, but now I can think about refactoring my too grown son.

The new release of PloneboardNotify doesn't give us many new features but is not this the real focus of this article.

This add-on was already available and used in production environment, and one of the first effort was to keep Plone 2.5 compatibility.
The same is for the new 0.4 release (and maybe Plone 2.5 compatibility will continue until all of our customer will drop this version).

So? What is the problem?

Thanks for testing

Sometimes when you develop something that is useful for a single site, it became magically useful for other... but sometimes you are too stupid (and lazy) to understand it.
Let's go back to Ploneboard: after all the notification e-mail after a new forum discussion/response is a wanted feature (worst... an expected feature), not available in Ploneboard (that, even if it isn't perfect, is the only mature choice available right now on Plone to have a forum).

PloneboardNotify is a good example of a bad way to start a product... developed fast but with no eye on good OOP, without thinking about make it extensible... not tested at all. It was only a stupid event script that send e-mail (luckily this old version isn't available or any public SVN so the Story will not judge me).

First public released versions were only more "user friendly", making it usable in any context where you have Plone and Ploneboard. Maybe they are good release but was clean the need of refactoring: but refactoring is someway a dangerous task (the code is working... why I must spend my time making it better only to get the same features and be forced to test all feature and behaviour from scratch? I'm sure to remember what I need to test?)!

The problem there was (and is also now) the "core" (please... don't look at it!). Tests at every release were done by me (and my name is not Funkload) manually playing with the browser, repeating the same operation on Plone 2.5 and 3. Time after time the core grow as new feature is added... Tests are every time more expensive and boring...

What is changed now? Nothing! PloneboardNotify is still a mess... but now it's a tested mess!

Future

The primary effort of this release was adding a complete functional tests coverage of all features (for both Plone 2.5 and 3 versions). After that, thanks to the help of Nicolas Laurance, I also added the HTML e-mail feature.

Now I have no fear to make changes to the code core... also in this release I removed some stupid piece of code (after completing tests!) and introduce adapters. Having tests available now will speed up dramatically the develop process of new features.

Next steps will be to reach a better OOP and making the product more customizable by other developer in their sites (like customize the e-mail template in some simple way).

Lessons learned

  • Don't be lazy. You can make this code more reusable. Always.
  • Don't be lazy. Write tests! Better: you will became lazy if you don't write tests because testing manually is very boring and you'll begin skipping some action!
  • Don't be stupid. You can't make deep refactoring and expect that all will work after you've finished, so...
    make tests! ;-)

Mar 11, 2010

Careful with that ajax, Eugene

by Alessandro Pisa — last modified Mar 11, 2010 04:40 PM

Ajax calls are an invaluable and powerful tool to deploy pleasant user interfaces, but some attention must be paid to avoid bad surprises.

In these days it happened to me to work on a couple of custom Plone edit forms using ajax calls to simplify user data entry.

At a first glance, the user experience was great, but under the hood the whole machinery was hiding potential problems, the reason being that in both cases the ajax calls used in the form were relative to the document path, even when if the document was in the factory!

This means that every time the ajax call was invoked, additional security checks were performed and in the case of the documents inside the factory other this lead to an unwanted creation of temporary documents!

The security checks and the portal factory abuse increased the response time and could potentially raise conflict errors.

During the development phase the problem is hardly noticeable, but on a production server it will probably make the form unusable, especially if you complex security checks are needed.

The solution was simply to call the views with another context (in those cases the container). 

Lesson learned: be careful to the context of your ajax call

Mar 01, 2010

Integration of PloneGazette with plone.app.discussion

by Federica D'Elia — last modified Mar 01, 2010 11:25 AM
Filed Under:

The new product collective.discussionintegration.plonegazette provides the integration of PloneGazette and plone.app.discussion.

The product plone.app.discussion is becoming the standard way to add comments in Plone. If both products plone.app.discussion and Products.PloneGazette are installed the creation of any PloneGazette content type fails, because PloneGazette content types not provide the adapter for "IConversation":

Traceback (innermost last):
  ...
  Module plone.app.discussion.catalog, line 29, in total_comments
TypeError: ('Could not adapt', <NewsletterTheme at /ausl/newslettertheme.2010-01-26.2440135204>, <InterfaceClass plone.app.discussion.interfaces.IConversation>)

 

 

To solve the problem we set an adapter for the types defined in Products.PloneGazette. This adapter provides the interface "IConversation" of plone.app.discussion. The adapter provides the attribute "total_comments" and the method "enabled", which returns False (means that the commeting is disable).

<adapter
      for="Products.PloneGazette.interfaces.INewsletterTheme"
      factory=".newsletter.NewsletterConversation"
      provides="plone.app.discussion.interfaces.IConversation"
      />

 

So you can create objects Newsletter without any problem.

Unfortunately PloneGazette does not define an interface for each content types, so through zcml we say that these content type implements a particular interfaces.Then we give the adapter for those interfaces.


The new product collective.discussionintegration.plonegazette makes possible the creation of the PloneGazette content types if there is an installation of plone.app.discussion in your instance.

http://svn.plone.org/svn/collective/collective.discussionintegration.plonegazette/

 

 

Feb 15, 2010

Do not use "print". Again plone_log is your friend

by Luca Fabbri — last modified Feb 15, 2010 10:11 AM
Filed Under:

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)

by Stefano Marchetti — last modified Jan 13, 2010 08:30 AM

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".

Dec 14, 2009

collective.flowplayer_toolbar: adding accessibility in an unobtrusive way

by Luca Fabbri — last modified Dec 14, 2009 09:43 AM

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 Pignatti — last modified Dec 03, 2009 06:42 PM
Filed Under:

cms vendor map

Full report available here

Nov 25, 2009

A cloud of colors in Plone

by Irene Capatti — last modified Nov 25, 2009 07:00 AM
Filed Under:

A small customization to Vaporisation's template, an excellent product for viewing tagcloud.

TagCloudVaporisation (also available as an egg) can display on your site a portlet with the cloud of the keywords used in the site.
If you are not satisfied with the standard monochrome display, you can quickly customize the template to add the CSS classes that give more color.

Copy the original template cloud.pt in your browser folder on your Plone theme (the classic theme created with paster).

Go to the configure.zcml file in the same folder and add these few lines: 

...
<include package="vaporisation"/>

<!-- Portlet tagclouds -->
  <plone:portletRenderer
         portlet="vaporisation.interfaces.IVaporizedCloud"
         template="cloud.pt"       
         layer=".interfaces.IThemeSpecific"
         />
...


Save and Close.
Now open your file cloud.pt. First, you could add to portlet a specific  css class:

<dl class="portlet portlet-tagcloud"
    i18n:domain="vaporisation"
    tal:attributes="id string:portlet-${context/getId}"
...


Moved a bit lower down, where tags are defined:

<a href=""
   tal:content="tag/name"
   tal:attributes="style string:font-size: ${tag/size}%;;;
                   href string:${link}${tag/name};
                   title string:${tag/name} (${tag/weight});" />


Add to the attributes list the CSS class:

<a href=""
   tal:content="tag/name"
   tal:attributes="style string:font-size: ${tag/size}%;
                   class python:'size_'+str(tag['size'])[:2];
                   href string:${link}${tag/name};
                   title string:${tag/name} (${tag/weight});" />


There is no need to change much, nor to extend the original python class.
In this way each different tag size will be associated with a CSS class like "size_10", "size_11" , ...,  that you can assign a color: 

...
.vaporized-tag a.size_13 {
    color: #006600;
}
.vaporized-tag a.size_14 {
    color: #008080;
}
.vaporized-tag a.size_15,
.vaporized-tag a.size_16 {
    color: #761911;
}
...


The end result will not be very different from this ... look at the bottom of the page :)

Nov 18, 2009

Deliverance, tips and tricks

by Irene Capatti — last modified Nov 18, 2009 08:00 AM

When to use regular expressions and "abort".

The attempt to use Deliverance on a Plone site which must also provide users all the functionality of the backend could be more difficult than expected.
Should be evaluated each case involving the opening of a popup or overlay javascript, because without the appropriate rules of match would get a beautiful Internal Server Error or a very nice "zoom effect" (in the popup will be reloaded the entire site) .

How to solve the problem?

Putting on top of our file rules.xml the match for all addresses that should not be filtered by Deliverance.

For the popup Related Items:

<match path="regex:^(.*/VirtualHostRoot|)/.*referencebrowser_popup$" abort="1" /> <match path="regex:^(.*/VirtualHostRoot|)/.*referencebrowser_popup$" abort="1" />


To view in a news  the image in original size:

<match path="regex:^(.*/VirtualHostRoot|)/.+/image_view_fullscreen" abort="1" /> <match path="regex:^(.*/VirtualHostRoot|)/.+/image_view_fullscreen" abort="1" />


For some of the basic tools of TinyMCE, including uploading files and images:

<match path="regex:^(.*/VirtualHostRoot|)/tinymce-upload$" abort="1" />

<match path="regex:^(.*/VirtualHostRoot|)/.+/plone(image|link)\.htm$" abort="1" />

<match path="regex:^(.*/VirtualHostRoot|)/.*/plugins/table/(table|row|cell|merge_cells)\.htm$" abort="1" />

<match path="regex:^(.*/VirtualHostRoot|)/.+/advanced/(source_editor|anchor)\.htm$" abort="1" />


Every time a new TinyMCE tool is enabled not forget to make sure it works properly ;)

Understood the principle, is easy to customize and improve the regular expression to fit our needs!

Nov 16, 2009

A Tiny step for more accessibility in Plone

by Luca Fabbri — last modified Nov 16, 2009 09:41 AM

In last months I'm keeping updated a branch of TinyMCE that can be very interesting for Italian users of Plone (but not only...)

For a preamble for all who didn't know nothing about it, lets me say some words on the Italian law for accessibility: the so called Stanca Act.

The Italian Legislation on Accessibility force all newly created public websites to keep 22 requirements, mainly taken from the WCAG 1.0.

For how Plone is designed (trying to fulfil the WCAG at AA level) a lot of required work is just done (I really like when this happen)!

There are only 2 requirements that keep our head busy every time we develop a new site for an Italian public agency:

Requirement 1
The (X)HTML must follow the Strict DTD.
Requirement 10
"[...] associate data cells and header cells in data tables that have two or more logical levels of row or column headers."

For us the requirement 1 is a fight against the Transitional DTD of Plone (see also the #4379). Of course, this mean we are always forced to fix manually some Plone templates, but at the end after 4 year this become a well know job!

The real problem is the XHTML code that users put inside the WYSIWYG editor... this must provide us XHTML Strict code someway!

When Kupu was the Plone choice this was a difficult... sometimes our choice was to put a layer between the editor work and the end user, fixing the code using the uTidylib!

In the perfect world the WYSIWYG editor itself must return us the XHTML Strict code...

Again: the requirement 10 is also a WYSIWYG editor problem. Kupu is not helping us to add additional cell info on created tables.

Welcome TinyMCE

The future (but already available) WYSIWYG editor for Plone 4 is TinyMCE.

The output code of TinyMCE is "more strict" than the Kupu ones... only some minimal fixes are needed. If facts the only validation error found right now if the use of the type attribute for ordered and unordered list (not available in XHTML Strict).

We are keeping updated a TinyMCE branch you can download and test from the collective; it fix the 2 problems described.

First of all: it's not using the type attribute again, but instead it applies a CSS class. An additional small stylesheet make the rest. For details see changes.

The other missing feature is to help the editor to add more attribute to table cells and headers. The simpler solution from the W3C is to provide the scope attribute.

When I started this task I was sure that this was going to steal me a lot of time... but again TinyMCE was a nice surprise!

The patch applied is simple; for some reason TinyMCE support the scope natively but it's disabled (probably only in the Plone version?). As you can see in changes done, my work was very quick (and again: I like when this happen)!

And now?

Keeping updated the code is a quite simple task, but I don't like the idea to branches forever. Also note that:
  • The first fix above is also valid for XHTML Transitional pages
  • The new scope attribute feature can be useful also outside a Stanca Law environment.

So?

We proposed to merge those changes in the TinyMCE core!

Keep one eye on #115 and #131!

Nov 13, 2009

How to write funkload test in few minutes

by Andrew Mleczko — last modified Nov 13, 2009 04:50 PM

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

by Andrew Mleczko — last modified Nov 07, 2009 06:12 PM

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.

http://rupy.eu/about/


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.

 

Nov 05, 2009

Lotus knows superenaLOTUS makes you win!

by Fabio Pignatti — last modified Nov 05, 2009 06:55 PM

 

Lotus Knows

 

In about one week we will be live! It's time for the 3rd Italian Lotus Users Group events (aka Dominopoint.it). So it's time to a little preview about my session (in italian):

 

Lotus knows superenaLOTUS makes you win! 

 

You have to attend my session to discover the details ...

Oct 16, 2009

Fast content import

by Andrew Mleczko — last modified Oct 16, 2009 08:19 PM

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 ;-)

 

 

Oct 14, 2009

New version of redturtle.video

by Federica D'Elia — last modified Oct 14, 2009 12:15 PM
Filed Under:

Released version 0.2.0beta of redturtle.video

A new version of redturtle.video was released on pypi:

http://pypi.python.org/pypi/redturtle.video/0.2.0beta

The package redturtle.video is a video support for Plone, based on collective.flowplayer.
In the new version of redturle.video two new fields are added to content types Video files and Video link. These new fields are "Year" and "Duration".

The information on the lenght of video is achieved through the use of packages: 'hachoir_core', 'hachoir_metadata' and 'hachoir_parser'.

The "Video Gallery" portlet shows content image fields taken from videos. In the new version "Video Gallery" portlet shows also the new informations on the year and duration of the video and also the title of the video.

Oct 06, 2009

Improve the compatibility of collective.plonetruegallery

by Federica D'Elia — last modified Oct 06, 2009 10:35 AM
Filed Under:

I created a branch of the product collective.plonetruegallery, extendible.gallery, which allows to use the features of the package for new types of content and not only for the type "Gallery".

I tried to use the functionality provided by the product collective.plonetruegallery, such as the view "gallery", for my content type, and I had a problem: these features are applicable only to the content type "Gallery". This is because in the code of the package conditions are evaluated on the value portal_type of the content type, eg. if(object.portal_type == 'Gallery').

So I changed some parts of the original product by ensuring that the controls are no longer performed on the value portal_type of the type of content, but on the interfaces implemented by the type of content. In this way the functionalities of collective.plonetruegallery can be applied to any type of content, different from "Gallery", if it implements the interface "IGallery", eg.: IGallery.providedBy (object).

I take advantage using my content type "Cartridge" that extends ATBTreeFolder, which functions as a folder can hold a large number of elements, rather than the type of content "Gallery" which is not a large folder, and then was not suitable for my purposes. But the point is that I could still use the view "gallery" of collective.plonetruegallery to view images from the cartridge, because my type of content implements the interface "IGallery".

I have proposed these changes to the developers of the product and now see if they are interested in applying this modern approach!

Oct 04, 2009

Hidden Javascript Jewels inside Plone!

by Luca Fabbri — last modified Oct 04, 2009 03:09 PM

The basic Plone installation rely on some little javascript sources that can be very useful.

Right now Plone is filled with a lot of jQuery javascript script for obtain UI effects. Every time you need an effect that Plone has, you must before ask to you: I'm sure that I only need to write down some good HTML, and nothing more?

Please not that even if this page try to integrate the same examples reported, you can't really see them working due to CSS issue. Use Firebug "Inspect element" feature to see how the javascript is changing the DOM.

Expand/collapse like "history" does

The javascript jem responsible of this is collapsiblesections.js.

It's javascript docstring says:

/* - collapsiblesections.js - */
/*
 * This is the code for the collapsibles. It uses the following markup:
 *
 * <dl class="collapsible">
 *   <dt class="collapsibleHeader">
 *     A Title
 *   </dt>
 *   <dd class="collapsibleContent">
 *     <!-- Here can be any content you want -->
 *   </dd>
 * </dl>
 *
 * When the collapsible is toggled, then the dl will get an additional class
 * which switches between 'collapsedBlockCollapsible' and
 * 'expandedBlockCollapsible'. You can use this to style it accordingly, for
 * example:
 *
 * .expandedBlockCollapsible .collapsibleContent {
 *   display: block;
 * }
 *
 * .collapsedBlockCollapsible .collapsibleContent {
 *   display: none;
 * }
 *
 * If you add the 'collapsedOnLoad' class to the dl, then it will get
 * collapsed on page load, this is done, so the content is accessible even when
 * javascript is disabled.
 *
 * If you add the 'inline' class to the dl, then it will toggle between
 * 'collapsedInlineCollapsible' and 'expandedInlineCollapsible' instead of
 * 'collapsedBlockCollapsible' and 'expandedBlockCollapsible'.
 *
 */


This piece fo code can be great for obtain the same sexy expand/collapse feature that you see all around Plone UI.

For example, I can use here this code:

<dl class="collapsible collapsedOnLoad">
    <dt class="collapsibleHeader">
      See the RedTurtle Hidden logo
    </dt>
    <dd class="collapsibleContent">
      <img alt="The RedTurtle Logo" src="http://www.redturtle.net/logo.jpg" />
    </dd>
 </dl>


And what is the results?

See the RedTurtle Hidden logo
The RedTurtle Logo

Dropdown menus

Wow! Can you believe that the dropdown menus you see in the working area of Plone (like "View", "Add portal content", ...) are only a piece of simple HTML and a magic javascipt does all the work?
The script this time is dropdown.js.

It says:

/* - dropdown.js - */
/*
 * This is the code for the dropdown menus. It uses the following markup:
 *
 * <dl class="actionMenu" id="uniqueIdForThisMenu">
 *   <dt class="actionMenuHeader">
 *     <!-- The following a-tag needs to be clicked to dropdown the menu -->
 *     <a href="some_destination">A Title</a>
 *   </dt>
 *   <dd class="actionMenuContent">
 *     <!-- Here can be any content you want -->
 *   </dd>
 * </dl>
 *
 * When the menu is toggled, then the dl with the class actionMenu will get an
 * additional class which switches between 'activated' and 'deactivated'.
 * You can use this to style it accordingly, for example:
 *
 * .actionMenu.activated {
 *   display: block;
 * }
 *
 * .actionMenu.deactivated {
 *   display: none;
 * }
 *
 * When you click somewhere else than the menu, then all open menus will be
 * deactivated. When you move your mouse over the a-tag of another menu, then
 * that one will be activated and all others deactivated. When you click on a
 * link inside the actionMenuContent element, then the menu will be closed and
 * the link followed.
 *
 */


So you only need to design an HTML dl structure like this:

 <dl class="actionMenu" id="myDummyMenuId">
   <dt class="actionMenuHeader">
     <a href="some_destination">Open the magic dropdown</a>
   </dt>
   <dd class="actionMenuContent">  
       <img alt="The RedTurtle Logo" src="http://www.redturtle.net/logo.jpg" />
   </dd>
 </dl>


Here follow the example usage

Open the magic dropdown
The RedTurtle Logo

Conclusion

There is a lot of Magic behind Plone, but thanks to jQuery and a smart infrastructure you can use this Magic for your needs!

Sep 24, 2009

How to revive an unstartable Plone 3.2.2 under windows XP Pro SP3

by Cesare Brizio — last modified Sep 24, 2009 07:55 PM
Filed Under:

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

 

  • Then, still not entirely trusting the Windows Service interface, I try to start the service manually:
  •  C:\Programmi\Plone\python\python.exe C:\Programmi\Plone\parts\instance\bin\zopeservice.py start
  • Execution returns the following line:
  • Starting service Zope_78966557
  • Now the plone controller sees that the instance is running and enables all its functions, including the ZMI
  • Under "Services", the service is up and running
  • Service may be freely started and stopped both from the PC and from the window's "Services" panel. 
  • Plone works fine
  • 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 07, 2009

    Solr explanations in collective.solr search results

    by Andrew Mleczko — last modified Sep 07, 2009 12:22 PM
    Filed Under:

    If you are using Solr score boost configuration, sometimes you need to know how certain document has been scored. Now you can see Solr explanation in Plone search results.

    I'm still working on collective.solr branch. To help our customer to understand how certain documents has been scored, I've included in Plone search results an configurable option - debug query.

    Configuration

    Using it you can check directly in Plone, Solr score explanation (it's toggled by jQuery).

    hidden:

    Hidden explanation

    and unfold:

    Full explanation

    Sep 03, 2009

    Solr score in collective.solr

    by Andrew Mleczko — last modified Sep 03, 2009 08:44 PM
    Filed Under:

    I've recently created a branch merging rt.solr with collective.solr. You can now boost search results' relevancy directly from Plone configuration

    For one of our customer we have been developing Solr score configuration in Plone. After a short discussion with witsch we have decided to contribute our efforts and merge everything to collective.solr branch. This is just a simple configuration panel with additional score query builder. Every score-boost entry has 3 fields: index, value and score. In current implementation if you leave value empty - it will be populated with SearchableText index value - when building the query. This approach allows flexibility our customer needs.

    Let's assume you want to sort results as follow:

    • Description has a query boost 10.0
    • portal_type=Document has a query boost 15.0
    • review_state=published has a query boost 20.0

    In this way you can boost Description index (for which the value will be taken from SearchableText) and portal_type index (for which you can define the value manualy) at the same time.

    to-do: we would like to add as an option Solr score explanation in search results (for users who want to know why certain document has certain score).

    We have found also some problems with Lucene proximity algorithm which can give some problems (it should be configurable in Solr 1.4.0).