May
May 10, 2010
Unchained melody
Collection concatenation can be done in many ways. A fairly underused way is to use the builtin chain method
Let's suppose you have to concatenate several collections objects, e.g.:
>>> a=range(3)
>>> b=set('ale')
>>> c=(a,b)
One easy way to do that is to create an empty list and use the extend method
>>> cat=[] >>> cat.extend(a) >>> cat.extend(b) >>> cat.extend(c) >>> cat [0, 1, 2, 'a', 'e', 'l', [0, 1, 2], set(['a', 'e', 'l'])]
But another elegant way do achieve the same result is to use the chain function from itertools
>>> from itertools import chain >>> chain(a,b,c) >>> cat=list(chain(a,b,c)) >>> cat [0, 1, 2, 'a', 'e', 'l', [0, 1, 2], set(['a', 'e', 'l'])]
This is especially useful when you have big amount of data because the result of the chain function is an iterator
Document Actions
How to make your team mates think you are someway useful
Disclaimer: vi integralist should skip this post :)
During a technical meeting here in RedTurtle, me and my colleagues were exposing fancy stuffs about software development and I was amazed that the attention of my team mates was triggered by me using a self made Pydev template to insert the encoding on top of Python files.
So here, I am reporting this to the whole planet, hoping someone else will appreciate this simple time saving tip :)
Adding a new template in Pydev is really easy, just go to Window -> Preferences... A configuration window should appear (see image below).

Navigate the tree panel on the left: Pydev -> Editor -> Templates and add click on the New button.
Another window will appear, where you can insert a name for your template (in my case utf8), a description (Insert encoding in the file) and the text to be inserted when this template is used (# -*- coding: utf-8 -*-).
With this template configured, insert che utf-8 encoding in to a file is just as easy as typing ut[CTRL]+[SPACE].
Document Actions
May 07, 2010
... and finally: what if they want tab inside Plone portlets?
A little demo (and the idea behind) for collective.portlettabber product
They want tab!
The request is quite common in recent layout that you can see all around the Web. Ok, "portlet" is common, but you can also find many examples of portlets with tabs.
What is this? The data inside portlets is split in sections that you can easily switch with a little Javascript code. The benefit is to put more information inside a tiny space, maybe showing to users only the most interesting ones when he arrive at your page.
Technically speaking this task is so simple that a blog post is not needed... but we don't know what kind of contents we want put inside the portlet tab.
Also the customer want to have the choice of use all (maybe the most part) of Plone portlets available is his installation... We really can't rewrite/overrider all portlets to get this...
...and finally (like everytime) accessibility. Data inside portlets must the accessible and the requirement 15 of the Stanca Act force us to make this available also with Javascript disabled.
Solution
Let's starts from what we can't lose:
- accessibility of the page without Javascript
- all Plone portlet usable as "tab"
For those two reasons the simplest way is to keep Plone portlet engine like it is. Plone portlets are working normally without Javascript, so why don't simply show tabs in only when Javascript is there?
This lead us to a solution. "Simply" generate portlet with tab using Javascript.
One more time again jQuery is our hero. The product add to Plone portal_javascript tool a new jQuery plugin for this. Is not a perfect plugin right now (is a composition of jQuery and normal Javascript OOP) but reach the target.
Here an example:
jq(document).ready(function() {
var generatedPortlet = jq.tabbedportlet();
generatedPortlet.makeTab("#portal-column-two .portletNews");
generatedPortlet.makeTab("#portal-column-two .portletCalendar");
generatedPortlet.makeTab("#portal-column-two .portlet-static-static");
jq("#portal-column-two .visualPadding").prepend(generatedPortlet.getPortlet());
});
When page is loaded a new Javascript object is created, and calling makeTab method you can "steal" other existing portlets all around the page (simply giving a jQuery selector, a DOM element or a jQuery object wrapping the portlet).
The method also has other features, look at the pypi page below for more.
Every call to makeTab will remove the portlet and move the DOM elements of the portlet inside a new ones (that, for now, is not inside the document yet).
When you have finished, just put the result of getPortlet method wherever you want.
The final effect is quite good... the demo will show you the page with disabled Javascript, then (long life to Web Developer's Firefox extension) it is enabled again and the page reloaded...
What next?
The product is not so simple to be used by Plone site members (this is not named collective.portlet.tabber...
)
A developer or a skinner must provide the additional Javascript inside a product/theme and he must know something about jQuery selectors... but after this starting setup... nothing more!
Another thing Ithat is not perfect is the Javascript structure, not a fully jQuery plugin. You can't fully rely on chaining right now.
More info?
http://pypi.python.org/pypi/collective.portlettabber
Document Actions
May 04, 2010
New collective.funkload releases
I have recently released a new version of collective.funkload and collective.recipe.funkload. There is one major improvment - funkload recorder is now working properly with collective.funkload scripts.
Here @RedTurtle we are heavily using funkload for acceptance and benchmarking tests. We have started using it in 2008 just after Bristol Performance Sprint. We have found even more useful with buildout recipe. The only missing part was the recorder. It's built-in Funkload itself, but it was not enabled in the recipe. Well - now it is ;-)
/ If you want to know how to include funkload in buildout project - check my previous blog /
Starting a recorder is quite easy:
$ ./bin/funkload record -p 8080 MyTest
for full usage call:
$ ./bin/funkload record --help
This will start proxy on 8080 port and save all your browser requests to MyTest funkload scenario. Now open your browser, change proxy configuration to localhost:8080 and click-through test case. When you finish - stop the proxy with Ctrl-C. Funkload will generate a test_MyTest.py file and notify you where you can find it. It should be now collective.funkload compatible - you can lunch:
$ ./bin/funkload test /path/to/test_MyTest.py
To test it.
Another small improvement is a PloneFLTestCase. It extends default funkload test case, implementing two additional methods helping with Plone content creation. Right now instead of using this approach:
folder_portal_factory = self._browse(server_url + "/coreloadtests/Members/" + self.user_id +"/createObject?type_name=Folder",
method='get',
follow_redirect=False,
description = 'Get folder portal factory')
folder_edit_url = folder_portal_factory.headers.get('Location')
folder_id = folder_edit_url.split('/')[-2]
folder_created = self.post(folder_edit_url, params=[
['id', folder_id],
['title', 'folder'],
['description', ''],
['description_text_format', 'text/plain'],
['subject_existing_keywords:default:list', ''],
['last_referer', 'http://localhost:8080/coreloadtests/Members/' + self.user_id + '/view'],
['form_submit', 'Save']],
description="Post /coreloadtests/Members/user...280843853/atct_edit")
new_folder_id = folder_created.url.split('/')[-2]
you can just do:
new_folder_id = self.addContent(
server_url,
portal_type='Folder',
params=[['id', 'id'],
['title', 'testing title'],
['description', 'testing description'],
['description_text_format', 'text/plain'],
['form.submitted', '1'],
['last_referer', ''],
['form_submit', 'Save']],
description='Create folder')
It doesn't do much, but for sure it helps you keep you test case readable.
Document Actions
May 03, 2010
No more "display:none" CSS rules!
Plone give us the right way to hide elements from the HTML page! Just use it... but what about jQuery?
It's not a news that accessibility is an important target of Plone... and Plone knows that CSS rules that use "display: none" are not readable by screen readers. However too often the display:none rules is used in themes, add-ons...
The problem is that this behavior is not so know outside the Plone core. Developers sometimes thinks that something that is hidden from the screen but present in HTML is accessible using a screen reader.
This is false.
How the screen reader works?
I'm not a real expert about it, but here what I learned.
When the page is loaded, the screen reader make a "screen-shot" of it and works on this. So elements that are hidden... for everyone!
So:
- Use display:none if you really want something in HTML that no-one can read.
- Do it like Plone does... apply the hiddenStructure class to your HTML element when you want something that can be accessible but not visible on you computer screen
What about Javascript/jQuery?
You like the jQuery .hide() and .show() features like me?
Well... keep in mind what you read some lines above... You use some .hide() call at load time? You use .hide() when clicking some links or buttons?
All this is not accessible...
Again, you need to think about using CSS given by Plone, so you must rely on the .addClass("hiddenStructure") and .removeClass("hiddenStructure") methods...
If you prefer give some new features to jQuery, you can also do something like this:
jQuery.fn.ploneHide = function() {
return this.each(function() {
jQuery(this).addClass("hiddenStructure");
});
}
jQuery.fn.ploneShow = function() {
return this.each(function() {
var e = jQuery(this);
if (e.is(":hidden")) e.show();
e.removeClass("hiddenStructure");
});
}
After this, you can rely on some new jQuery features!
jq(".documentByLine").ploneHide();