Plone
This is here to serve as contents for the atom/rss feed for Plone, also read by planet.plone.org.
How to avoid getting a too new Plone version
Plone 4 is nearing release candidate status, which is good news. But if you currently run a Plone 2/3.0/3.1 website, you do not want some add-on product (like Products.Poi) to surprise you by pulling in this brand new version. How can you make sure you are not caught unawares? Read on for a long example. For the impatient: just pin Plone.
Start
You have a website that is still running fine on Plone 3.0.6. (The story is the same or similar for Plone 2.x, 3.0.x and 3.1.x.) You have a buildout.cfg like this:
[buildout] parts = instance versions = versions find-links = http://dist.plone.org http://dist.plone.org/thirdparty eggs = elementtree [versions] plone.recipe.plone = 3.0.6 plone.recipe.zope2instance = 3.6 [plone] recipe = plone.recipe.plone [zope2] recipe = plone.recipe.zope2install fake-zope-eggs = true url = ${plone:zope2-url} [instance] recipe = plone.recipe.zope2instance zope2-location = ${zope2:location} user = admin:secret http-address = 8080 eggs = ${buildout:eggs} ${plone:eggs} zcml = products = ${plone:products}
Error
Now you want to add an issue tracker product to this website. Okay, you add Products.Poi to the eggs:
[buildout] ... eggs = elementtree Products.Poi
You run bin/buildout again and the result is an error:
Uninstalling instance. Updating plone. Updating zope2. Updating fake eggs Installing instance. While: Installing instance. Error: There is a version conflict. We already have: plone.app.layout 1.0.5 but Plone 4.0b1 requires 'plone.app.layout>=1.1.7dev-r23744'.
This is not the result that you hope to get. Seeing this error you might think you need to do something about that plone.app.layout version. But the real error here is that bin/buildout tries to install Plone version 4, where the buildout.cfg has Plone version 3.0.6. It does this, because the added Products.Poi package specifies a dependency on Plone 4, specifically Plone>=4.0a1.
So why does bin/buildout not quit with a more informative error, like:
Error: There is a version conflict. We already have: Plone 3.0.6 but Products.Poi requires 'Plone>=4.0a1'.
The thing is, bin/buildout has no way of knowing that you have version 3.0.6, because this Plone version is not "eggified". Simply speaking, what this means is that there is no link to Plone 3.0.6 on this page: http://pypi.python.org/simple/Plone. There you will only find Plone 3.2 and higher, as that is the first eggified Plone version. For Plone 3.0.x and 3.1.x, the plone.recipe.plone buildout recipe is used to pull Plone and the other not-eggified products into your buildout. But this does not help when a third party package has a dependency on Plone: bin/buildout will see this and pull in the latest Plone egg it can find, resulting in errors like above.
Fake eggs
So how do we solve this? We could try to fake having a Plone egg. plone.recipe.zope2install already fakes a Zope2 egg, and lots of zope.*, zope.app.*, and other eggs, next to its main task of actually installing Zope2. You could say that plone.recipe.plone is a workaround for the not-eggified Plone and ``plone.recipe.zope2install is a workaround for the not-eggified Zope2. So, how could you fake a Plone egg? You add Plone to the additional-fake-eggs option of the recipe:
[zope2] recipe = plone.recipe.zope2install fake-zope-eggs = true url = ${plone:zope2-url} additional-fake-eggs = Plone
If you comment out the Products.Poi egg in buildout.cfg for a moment and rerun bin/buildout you will now have a file fake-eggs/Plone/Plone.egg-info with these contents:
Metadata-Version: 1.0 Name: Plone Version: 0.0
If you do not like that version string 0.0, you could specify a different version in the recipe config:
additional-fake-eggs = Plone = 3.0.6
But of course later you will decide to update your buildout.cfg to use plone.recipe.plone=3.1.7 and will forget to update the additional fake egg version, leading to confusion, so you might as will accept the default 0.0 version.
Anyway, we have a fake egg now, but does it actually help us? Errr... no. Make sure Products.Poi is listed in the eggs again and rerun buildout:
Error: There is a version conflict. We already have: plone.app.layout 1.0.5 but Plone 4.0b1 requires 'plone.app.layout>=1.1.7dev-r23744'.
That is the same error we got earlier. So why did it not work? That is easy: the picked Products.Poi version (2.0a1 at the time of writing) depends on Plone>=4.0a1, like we mentioned before. Plone 0.0 is available in the buildout due to our additional fake egg, but this version does not meet the requirements of Products.Poi, so bin/buildout gets the latest available Plone version instead, leading to problems.
Our previous solution would have worked if the picked Products.Poi version would have specified a dependency on any Plone version (Plone) or for example any Plone version lower than 4 (Plone<=4.0dev). So it might have its merits, but it is not enough in our case. In fact, I can imagine that some add-on products specify a dependency on Plone expecting to get at least Plone version 3.2, as that is the first eggified Plone version. Having a fake Plone egg would go against that expectation and might cause problems. So if you use this, use it with care.
Pin Plone
Our problems is still not solved. But the solution is only one line away. We add a version pin for Plone:
[buildout] ... versions = versions ... [versions] plone.recipe.plone = 3.0.6 plone.recipe.zope2instance = 3.6 Plone = 0.0
When we now run bin/buildout again with Products.Poi in the eggs, we get this error:
The version, 0.0, is not consistent with the requirement, 'Plone>=4.0a1'. While: Installing instance. Error: Bad version 0.0
This error message is still not ideal, but at least this does not lead us on a wild goose chase after plone.app.layout, but clearly points out that some package depends on a newer Plone version than we want.
Debugging
If you now run bin/buildout in verbose mode by adding one or more v options, you get more info, which hopefully helps in debugging this (bin/buildout -v):
Getting required 'collective.watcherlist>=0.2' required by Products.Poi 2.0a1. We have the best distribution that satisfies 'collective.watcherlist>=0.2'. Picked: collective.watcherlist = 0.2 Getting required 'collective.autopermission' required by Products.Poi 2.0a1. We have the best distribution that satisfies 'collective.autopermission'. Picked: collective.autopermission = 1.0b1 Getting required 'Products.DataGridField>=1.8a1' required by Products.Poi 2.0a1. We have the best distribution that satisfies 'Products.DataGridField>=1.8a1'. Picked: Products.DataGridField = 1.8a1 Getting required 'Products.AddRemoveWidget>=1.4.2' required by Products.Poi 2.0a1. We have the best distribution that satisfies 'Products.AddRemoveWidget>=1.4.2'. Picked: Products.AddRemoveWidget = 1.4.2 The version, 0.0, is not consistent with the requirement, 'Plone>=4.0a1'. While: Installing instance. Error: Bad version 0.0
At this point, without further information, I would probably work my way up from the bottom and start investigating if Products.AddRemoveWidget 1.4.2 specifies a dependency on Plone (which it does not), and then checking Products.Poi 2.0a1 (bingo). Of course in this case we do know that the buildout worked fine before and is throwing errors after adding Products.Poi to the eggs. So starting the investigation with Products.Poi would make the most sense here. But knowing where to start looking is a matter of knowledge, experience and luck. Also: do not change too many things at the same time: do not update to a new Plone and Zope version and at the same time add ten new products in your buildout.cfg; it will only confuse you when things start going wrong.
In this case, at http://pypi.python.org/pypi/Products.Poi you currently see a list pointing to versions 2.0a1 and 1.2.8. Version 1.2.8 does not specify a dependency on Plone (speaking as Poi maintainer: nor will future 1.2.x versions), so you pin that version and things should work again:
[versions] plone.recipe.plone = 3.0.6 plone.recipe.zope2instance = 3.6 Plone = 0.0 Products.Poi = 1.2.8
Dump all picked versions
Indeed, running bin/buildout now works. This might change though when one of the other not-pinned packages is updated and has unwanted changes or starts depending on Plone 4. So to top this overly long example off, we will add the buildout.dumppickedversions buildout extension, run bin/buildout and copy the reported versions to our buildout.cfg, resulting in the following file:
[buildout] extensions = buildout.dumppickedversions parts = instance versions = versions find-links = http://dist.plone.org http://dist.plone.org/thirdparty eggs = elementtree Products.Poi [versions] Plone = 0.0 Products.AddRemoveWidget = 1.4.2 Products.DataGridField = 1.6.1 Products.Poi = 1.2.8 buildout.dumppickedversions = 0.4 distribute = 0.6.10 elementtree = 1.2.7-20070827-preview plone.recipe.distros = 1.5 plone.recipe.plone = 3.0.6 plone.recipe.zope2install = 3.2 plone.recipe.zope2instance = 3.6 python-openid = 2.0.1 zc.buildout = 1.4.3 zc.recipe.egg = 1.2.2 [plone] recipe = plone.recipe.plone [zope2] recipe = plone.recipe.zope2install fake-zope-eggs = true url = ${plone:zope2-url} [instance] recipe = plone.recipe.zope2instance zope2-location = ${zope2:location} user = admin:secret http-address = 8080 eggs = ${buildout:eggs} ${plone:eggs} zcml = products = ${plone:products}
Fake it after all?
Incidentally, if you have an add-on product that simply depends on Plone without a minimum version, you would now get an error like this when running bin/buildout:
Getting distribution for 'Plone==0.0'. While: Installing instance. Getting distribution for 'Plone==0.0'. Error: Couldn't find a distribution for 'Plone==0.0'.
If you understand what you are doing you can still use the fake egg trick from earlier to fix this. But probably you should instead figure out which add-on is pulling in Plone, and see if an earlier version of that add-on is available that works with your Plone version without having to resort to faking eggs.
Note that for proper fake eggs, you will want to use at least version 3.0 of plone.recipe.zope2install, and probably the latest 3.2.
Summary
To avoid new Plone versions from being pulled in by add-on products when you are on a not-eggified Plone version (2.x, 3.0.x, 3.1.x), just add a version pin for Plone:
[buildout] ... versions = versions ... [versions] Plone = 0.0
This will not magically solve your buildout problems. Basically, this tells bin/buildout that it should quit with an error when a package is depending on a Plone version. Hopefully the lines before the error message have a hint about which package this is; otherwise try bin/buildout -v to get more verbose information.
Python Users Netherlands meeting, 24 March 2010
Summary of the meeting of the Python Users group Netherlands.
This PUN meeting is organized and sponsored by Maykin Media and go2people. The location is the ABC Treehouse (American Book Center), Amsterdam. We have this location for free once a month, for the next year. So if you have ideas here for community projects, let us know. Next meeting is July 14th. It could be here, but if there is a different spot, that is good as well.
Like always, 2 larger presentations (half an hour), 5 lightning talks, and drinks afterwards.
Idea: we could use this location for a 'code dojo', a coding practice. Get together with smart people that know about coding and build something nice. Or a pair programming dojo: take a simple problem and work on it with two people.
Konrad Delong: Concurrency in Python
Student at the Vrije Universiteit Amsterdam, via the Erasmus exchange program; I come from Poland. I am writing my master thesis on concurrency in python. Concurrency is about simultaneous computations, potentially interacting with each other. Could be running on separate cores or cpus.
Python has two modules for this: thread (low level, in C), and threading (more high level, more advanced threading primitives, more object oriented).
A lot of people do not like threading in Python because of the Global Interpreter Lock (GIL). Only a single thread can run code at one point. Other threads can start any time. Every 100 ticks (by default) the interpreter lock is released so another thread can take over. Also done on IO blocking operations. What this means is that you have no gains on multicore systems. Performance can even get worse for multiple cores, because threads battle for the GIL. Also, the latency in response to events is larger because of the GIL. On single core systems the performance with the GIL is quite good. It is a safe environment for C extensions: you can make some handy assumptions about the environment. Also, you do not have to use threading.
Some people try to remove the GIL. Greg Stein tried it; slower for single core machines, hardly faster on multicore; similar for python-safethread. There is PyPy and Unladen Swallow. There is also a policy on dropping GIL in cPython, which can be used. Other solutions: processes instead of threads; Jython and IronPython, Async.
The multiprocessing module (python 2.6) looks a lot like threading. Almost the same, but not entirely. No implicit shared memory (global variables, imported modules). There needs to be some interprocess communication (IPC). Data needs to be serializable (picklable).
Asynchronous solutions have been present in python for some time, like the standard asyncore module. The Twisted web server does this explicitly. It has a reactor loop that registers callbacks that other code should call when it is ready with processing. Other option: greenlets; all threads run in the same interpreter, so the same thread. See modules Eventlet, Gevent, PyEvent; quite a lot happening there recently. Lower level: select, epoll, kqueue for more directliy talking to the operating system. Also look at Kamaelia, and Stackless python. These solutions can be better when you would otherwise need thousands of threads. Some of this is used by big online games, like Eve Online.
See the slides.
Albert Visser
From Apeldoorn. Started as programmer in Cobol. You need a jcl file (stream) to make an executable program. I made a program to create that jcl automatically.
Roald de Vries: Properties and methods
From Go2People. With @property you turn a method into a property. How does that work? It is not an object property, but a class property. But the class property is not the same as the object property, which is not what you would expect. Descriptors can optionally implement __set__ and __delete__. In the attribute search order, python does some checks to see what should be returned, and this is where the descriptors take their place. Functions are always descriptors. See among others Shalabh Chaturvedi: Python Attributes and Methods.
Roland van Laar: how to open beer bottles
This was a demo about opening beer bottles without an opener. Always useful information during a PUN. :-)
Gijs Molenaar: Computer Vision with Python
From http://gijs.pythonic.nl. I am studying still, and doing things with computer vision and python. Computer vision means: extracting information from images. An image is a matrix of pixels. Things you can do, are: convert the color space (Hue Saturation Intensity), so you can for example focus on just one colour; thresholding; clustering; line, geometry or edge detection. Usage can be: optical character recognition, human computer interfaces, surveillance, augmented reality, or even an artistic toy. In The Netherlands we have section control (trajectcontrole) on some roads now: check if a car keeps to the maximum speed over a certain section of road (basically turning it into maximum average speed). More info: book Computer Vision: Algorithms and Applications, by Richard Szeliski from Microsoft Research; see http://research.microsoft.com/en-us/um/people/szeliski/Book/
About OpenCV: Open Computer Vision. It is open source, over 500 functions, originally developed by Intel, for Windows, Linux and Mac. Structure: HighGUI module for the IO and the GUI, make windows, sliders, webcam interface; CXcore module, for datatypes and basic functions; CV module for all the interesting computer vision functions; ML for Machine Learning, for analyzing data that comes out of the CV.
He demoed a program, of just a screen full of code, that captured live images from his webcam and did line recognition.
Three APIs: new python wrapper (native C++), old python wrapper (using swig), PyOpenCV (Boost/Bjam + numpy). The old wrapper is usually available on your OS as a package (aptitude install python-opencv, port install opencv). I have packages for the new wrapper ready for upload. Manual compilation: advantage: full control, some optimizations. Book: Learning OpenCV.
Problems: a lot of people report problems with installations; sometimes buggy, with segmentation faults, in which case you usually need to use the code a bit differently; sometimes undocumented; almost useless mailing lists, far more questions than answers, except when you have a really interesting question.
Presentations and examples can be downloaded.
Klaas van Schelven: virtualenv and pip
A virtualenvironment (virtualenv) is an isolated environment where you can install packages with pip, without bothering already installed packages in other environment. So for instance you can use this as an easy sandbox for safe testing of an unknown package. virtualenv --no-site-packages dirname creates a virtualenv in the directory dirname. cd dirname; source bin/activate. Set export PIP_RESPECT_VIRTUALENV=true somewhere in your ~/.bashrc. This way pip install mypackage will figure out if you are in a virtualenv and act accordingly. With pip freeze > production_ready.txt you can get the currently used package list with the correct versions, which you can reuse later, with pip install -r production_ready.txt.
Remark from the crowd: never remove old versions of packages from pypi or from wherever; it breaks peoples software. So please please never do this.
Guido Wesdorp: pydirs
From http://pragmagik.com. pydirs is a simple python object database. First ideas: 'svnodb', an svn object database, but subversion turned out to be a nuisance. So now pydirs. Simple code base, less than 500 lines. Simple explorable storage format with just directories and basic datatypes as text files. Great for debugging as you can use the command line tools. Everything else is stored as pickles. API: typeregistry, database object, session object (get, commit, rollback), pydiritem object. Currently quite stable, and used in production. I hope to release it very soon.
Update: it has been released here: http://johnnydebris.net/pydirs.txt
See my brother Reinout's weblog for another summary.
A final look at Erik Rose: Plone 3 for Education
Erik Rose has written a book about: Plone 3 for Education. Here are my final impressions.
After my first impressions on the Plone 3 for Education book by Erik Rose, here are my final impressions. I will cover the whole book now. To make it very practical, for each chapter I will recommend which of my colleagues at Zest Software should read it. For some it will just be a reminder of what they already know, but freshening up your knowledge and perhaps picking up some small tips on the go are always good. Note that some have multiple roles, so someone may be listed first as trainer and later as programmer.
Chapter 1: Creating Courses
This is about creative application of the default Plone content types. It explains how to use some features of standard Plone, like collections, large folders and default pages. Recommended for Esther (Partner), Robin (Marketing/Sales), and Angela (Management Assistant).
Chapter 2: Calendaring
The Plone4ArtistsCalendar product is used as a nice way of showing events; this looks like a good solution for sites with lots of events. The chapter teaches best practices for using events and collections. You also get some tips about how best to apply security and permissions. Recommended for Esther (Partner), Robin (Marketing/Sales), and perhaps Mirella (Project Manager), mostly because they may be doing content management on some client sites or on our own site.
Chapter 3: Showcasing Personnel with Faculty/Staff Directory
The add-on product Faculty/Staff Directory can be seen as a departmental website in a box. It uses membrane, remember and relations. It is a versatile product, which could be useful in several occasions. Recommended for Jean-Paul (Partner) and Robin (Marketing/Sales): they should know this product is available; also recommended for the programmers (Mark, Fred, Vincent, me): they should see if this product fits the bill, before making something from scratch. It can also serve as a good example of how to use the membrane and remember products.
Chapter 4: Extending Faculty/Staff Directory
The standard product shown in the previous chapter is now extended using archetypes.schemaextender. Recommended for Mark, Fred and Vincent (programmers): look at this to freshen up your knowledge of archetypes.schemaextender (or for your first look at this).
Chapter 5: Blogs and Forums
This is a look at the out-of-the-box blogging potential of Plone (which may be enough), and at add-on products. Erik calls these "free as in puppies": they are cute, but you should be aware that they come with responsibilities. All add-on products that you may want to add in your site, should first be tested on a copy of that site, including trying to uninstall it. The QuillsEnabled and Scrawl products are introduced for blogging, including using them in combination if needed. For forums the judgement is clear: use Ploneboard. Recommended for Mark as consultant and Fred as consultant/trainer.
Chapter 6: Embedding Audio and Video
For embedding audio and video, Erik recommends collective.flowplayer as the most flexible and trouble-free solution. Plone4ArtistsVideo is mentioned once for podcasting support, but perhaps Plone4ArtistsAudio is meant, as that one is explained. In some cases, for example embedding YouTube videos, you need to write some pure html yourself, so enabling the object and embed tags is explained; I did not notice before that there was an embed-tab button that you can enable in Site Setup, Visual Editor, Toolbar. Again recommended for Mark as consultant and Fred as trainer.
Chapter 7: Creating Forms Fast
I already wrote about this chapter in my first impressions. Recommended for Esther (Partner), Robin (Marketing/Sales), Mark (Consultant), Fred (Trainer). This was a handy chapter for me as well; I just know Mirella has ten times more experience here than I do. :-)
Chapter 8: Styling Your Site
This chapter explains the Zope 2 way versus the Zope 3 way of theming. Depending on which parts of your site you want to style, you will need to learn both ways. You will learn about through-the-web versus development on the file system. You use paster for creating a basic theme product. Erik shows z3c.jbot as the easiest way of overriding templates from Plone's sometimes difficult viewlet and portlet machinery. Recommended for Mirella and Laurens (CSS Specialists) for perhaps a better understanding of why some things need to be done in a certain way.
Chapter 9: Going Live
This is all about buildout, a zeo setup, CacheFu, Squid and Apache. Recommended for the programmers when dealing with Squid instead of the varnish that we mostly use; and a fresh look at the CacheFu settings would not hurt.
Chapter 10: Maintenance, Backups, and Upgrades
The instructions to pack manually give wrong directions, which will have you end up in the ZMI in the Plone Site root, without a Zope Control Panel in sight. Instead you should simply go to Site Setup and then to Maintenance. Other than that, this chapter has no surprises, but if you come working for us as programming sysadmin this is the first chapter you should read.
Conclusion
Plone 3 for Education is a very practical book. It shows you a safe route through Plone land, giving solid advice that will keep you out of the pitfalls of this great CMS.
Disclaimer: I got this book for free from Packt Publishing in exchange for a review. Ordering the book via one of the links in this article will land me some money.
Presentations at Zest
This Friday we had various presentations and food at the Zest Software headquarters.
Every few months at Zest Software we have our so-called "eten en weten" meetings; literally: eating and knowing, but in Dutch it rhymes. Basically it means: presentations by colleagues at the end of the afternoon, then food, then more presentations, with some discussions sprinkled around. The later the evening, the more technical the presentations get, so the less technical colleagues can flee. :-) It is also a nice way to catch up with former colleagues who are invited; this time we were joined by Joris Slob; always a pleasure. Meet our strong team here.
Coaching
It started off with Esther and Jean-Paul introducing new coaching options for the team members. Everyone gets the chance to have a few talks per year with a coach, paid for by Zest. The coaches were also there to introduce themselves. A very nice option.
Fred: breathe in, breathe out
Then colleague Fred happily surprised us with a workshop about breathing techniques. In his spare time he sings in a choir, so he has experience here. Sorry, I don't think any pictures were taken. :-)
Laurens: featured features
Our CSS specialist Laurens showed some nice features he found on several websites. Ask him for some links. :-)
Joris: the semantic web
Now the floor was for former colleague Joris Slob, currently working at the Leiden Institute of Advanced Computer Science. He talked about the semantic web and the technologies that float around in that area. Web 1.0 can be summarised as: smart people put things on the web; less smart people only look at it. With web 2.0 lots more people can dump content, whether it is smart or not. But there is nothing fundamentally new about this web: it is just a different use of the same old techniques. For that you can look at what some call web 3.0: the semantic web. Computers currently do not understand the semantics of web pages. They fetch an html page and see something like this:
blah blah blah blah blah blah
blah blah important blah blah blah
Let Google search for images of jaguars and you will get both cars and animals. But try Google's Wonder wheel: it realises you could be looking for jaguar cars, jaguar parts, jaguar animals and more.
As human you have knowledge. What do you do with that knowledge? Where do you store it? Can you put it in a database? Our databases do not fit this reality very well.
In comes RDF, the Resource Description Framework. RDF offers user-defined relations, instead of a rigid database where all possible relations between items in tables have to be defined beforehand. RDF consists of triples: subject + predicate + object = fact. For example: Joris (subject) likes (predicate) Python (object). So the predicate is the relation between subject and object.
But how do you know who this "Joris" is? Lots of people are called Joris, at least in The Netherlands. So you use a URI, a Uniform Resource Identifier, like this: http://www.liacs.nl/~jslob/foaf.rdf#me
This URI uses the Friend Of A Friend (foaf) vocabularies. These describe relations between persons. In this example we get an xml representation of the RDF triples, but they can also be stored in the native RDF non-xml format.
Another part of the semantic web is OWL, the Web Ontology Language. (You may think this three letter acronym is in the wrong order, but the French would disagree with you; just ask our French colleague Vincent. Update: actually, see the section on the acronym in the encyclopedia for the real reason.) OWL gives greater expression possibilities. You also need reasoners. Reasoners can go through your knowledge base and find inconsistencies, or infer new relations. Fact 1: Joris is a human. Fact 2: humans have 2 legs. So we infer a third fact: Joris has 2 legs. Some inconsistencies can be resolved: "Obama is a good president" versus "Obama is a bad president" could become: 'John thinks "Obama is a good president"' and 'Lucy thinks "Obama is a bad president"'.
Then there are ontologies. Ontologies define possible relations in a knowledge domain. Examples are SIOC, Dublin Core, Foaf, Good Relations and Basic Geo Vocabulary. If you can reuse an existing one, that is very good, as you do not want to create your own if you can avoid it.
To get information out of a knowledge base, you can use SPARQL, which is a query language that looks a bit like SQL. To get everything, you would write:
SELECT ?s, ?p, ?o where {?s ?p ?o}Another part of the semantic web is formed by microformats. These embed meaning in html. Examples are hCards, hCalendar, RDFa (pushed by Google, blocked by Adobe for HTML5). Also: Google Rich Snippets. This can for example be used to have information about ratings (4 out of 5 stars) show up in Google search results.
For the python programming language you want to look at the rdflib library. Most readers of this blog will likely be familiar with Zope, so I'll mention that you can also use the ZODB (Zope Object DataBase) as a back end.
Finally, if you want to learn more, you should read this book: Programming the Semantic Web, by Toby Segaran, Colin Evans and Jamie Taylor.
Vincent: jQuery, plus libraries, plus Proxy
At this time the non-technical people made good their escape, and the rest buckled up to learn about the wonderful world of jQuery, several jQuery libraries, and the soon to be released jQuery Proxy, made by Vincent. He made the presentation with live demos using Django; there was also a pony somewhere...
The jQuery principle is: write less, do more. You usually do not have to care about differences between browsers. It has got great documentation.
Some libraries are:
- jQuery UI: the official UI for jQuery. It has themes, widgets, interactions (like draggable, droppable, resizable).
- jQuery Tools: less effects than jQuery UI, more web oriented, with tabs, tooltip, overlay, expose, scrollable.
You can find lots more on http://plugins.jquery.com/ which is basically a pypi or CPAN for jQuery, including a demo for each plugin. Some that Vincent uses are cookie, color and lightbox.
And now there is jQuery Proxy, written by Vincent. This gives easy integration of AJAX in python sites. At least it works in Django and Plone. You get jQuery syntax in python code and can send this back to the browser. It also allows using jQuery libraries/plugins. It could eventually replace KSS. The way you use it is for example this:
from jquery.pyproxy.django import JQueryProxy, jquery # The @jquery decorator handles the transformation of your results # into JSON so we can decode it on client side. @jquery def ajax_add_comment(request): # The JQuery proxy object helps us to manipulate the page the user sees. jq = JQueryProxy() # The data/form sent with Ajax just apear like a classical POST form. form = request.POST #we do some validation of the form. ... if errors: # We display an error message. jq('#my_error_message').show() return jq ... # We display a success message. jq('#my_success_message').show() return jq
The source is available on github and we will hopefully see a release next weekend. Very interesting!
Mark: DVCS
Next up was Mark, with a talk about Distributed Version Control Systems (DVCS), or as he liked to call it: git. :-) See his weblog for the slides. At Zest we are using subversion to store our code and share it among the developers. With subversion you have a central server that every commit goes to. But some would prefer doing local commits, so as not to disturb others with experiments or with a temporarily broken code state, or just because they are in a train and have no network connection. This is where distributed systems like git and mercurial or bazaar shine. You can still use a central repository if you want to though.
With git you have a complete local repository, which means it is much much faster, as you need less network traffic: basically the only times you need to connect to a different server are when you pull code (get new code from trunk or a branch) and when you push code (send your changes to a server). Checking in code is fast, because you do not need to do get fresh code first (svn up) to see if someone else changed some code, so you also do not get clashes when checking in, and the commit is local so that makes it extra fast.
Not everyone at Zest is sold on the idea of using git yet. For now we will keep using subversion. Those wanting to use git can use git-svn, and have been doing that already. If possible we'll try and keep our buildouts git-friendly; we have already created some client buildouts with the client packages directly in the buildout src directory instead of including it using infrae.subversion, mr.developer or svn:externals (though the last one is apparently less of a problem).
Maurits: collective.watcherlist
I was the last presenter of the evening. I talked about a client project, but there was a Non Disclosure Agreement involved, so I have probably already said too much. :-) So we will skip that and jump straight to my presentation about a new package I have created, called collective.watcherlist
collective.watcherlist is a package that enables you to keep a list of people who want to receive emails when an item gets updated. The main use case is something like Products.Poi, which is an issue tracker for Plone. That product lets you create an issue tracker. In this tracker people can add issues. The tracker has managers. Every time a new issue is posted, the managers should receive an email. When a manager responds to an issue, the original poster (and the other managers) should get an email. Anyone interested in following the issue, should be able to add themselves to the list of people who get an email.
The origins of collective.watcherlist also lie in the mentioned Products.Poi package, first created by Martin Aspeli and now maintained by me. A while ago I fixed some bugs in the email sending part of Poi, as sending international emails can be tricky. After this, I thought this part of the code was quite solid (the rest as well, actually :-)) and could be useful for other packages that needed to send out email. So I decided to factor this code out into a separate package. This also made some parts of Poi cleaner and simpler.
There is no release as of this writing, but the source code is in the collective. You may want to grab the buildout of a branch of Poi that uses it. That branch of Poi is meant for Plone 4. I should create a proper alpha release for that soon. The collective.watcherlist package itself works just fine on both Plone 3.3 and 4, though there are some minor test failures on Plone 3. The test coverage is at a solid 98 percent, so I am quite sure most bugs have been ironed out.
I showed what the package does by going through the code in the sample directory. For this blog entry I will resort to some copy-pasting from the readme file.
It is not a package for end users. Out of the box it does nothing. It is a package for integrators or developers. You need to write some python and zcml in your own package (like Poi now does) to hook collective.watcherlist up in your code.
collective.watcherlist might also be usable as a basis for a newsletter product. If you feel Singing and Dancing is overkill for you, or too hard to adapt to your specific needs, you could try writing some code around collective.watcherlist instead.
In its simplest form, the integration that is needed, is this:
- Register an adapter from your content type to collective.watcherlist.interfaces.IWatcherList. In a lot of cases using the default implementation as factory for this adapter is fine: collective.watcherlist.watchers.WatcherList
- Create an html form where people can add themselves to the watcher list.
- Register a BrowserView for your content type, inheriting from collective.watcherlist.browser.BaseMail and override its properties subject, plain and/or html.
- Create an event handler or some other code that gets the adapter for your content type and uses that to send an email with the subject and contents defined in the browser view you created.
That is it. There are currently no viewlets, portlets or other templates that you need to override, so it should be easy to fit into the theme of your website, provided you do not mind coming up with a UI yourself. The sample directory is a good spot to look for the basis of that though.
Future plans include:
- an option to send to all members (though this should already be very easy to do yourself),
- allow setting a different from-address,
- personalised emails, even if just with a footer to point to an unsubscribe option,
- optionally storing more info per subscriber, like a preference for plain text or html,
- more newsletter-like functionality, for example double-opt-in (similar to what the PasswordResetTool does when creating a Plone member).
A first look at Erik Rose: Plone 3 for Education
Erik Rose has written a book about: Plone 3 for Education. Here are my first impressions.
Plone 3 for Education is targeted at people working in education or in other larger organizations. You are the webmaster responsible for one or more websites of the organization. You are comfortable using Plone daily, but there just never is time to do everything that is needed. You want to delegate responsibilities to other users and wonder what is the best way to do that. The website needs some extra functionality and you would like to use an existing product for that; but which one is the safe bet for the future? And the website looks a bit outdated and could use some visual freshness. You have done a few tweaks in the Zope Management Interface, but have also heard that this is not the best way. So how do you make a nice theme these days?
If you recognize yourself in that description, then this book is for you. Hardened Plone programmers will not find much news here; still, most chapters give info about how best to use some third party products, like Plone4Artists Calendar and Faculty/Staff Directory. If you know what these products can do, you become a better consultant; and you know when to pick one of these products off the shelf instead of programming something totally new.
As the preface says, most chapters stand on their own. So the first thing I did, was to take on chapter 7: Creating Forms Fast. This is about PloneFormGen. My experience with PloneFormGen was mostly how to add it in a buildout, as at Zest Software we use this for quite a lot of clients. I do not think I have ever actually used it myself. So this looked like an interesting chapter to start with.
PloneFormGen is well maintained by Steve McMahon, who was one of the reviewers of this book, so you can be pretty sure the information in this chapter is correct.
The chapter starts out by telling you to "install PloneFormGen by adding Products.PloneFormGen to your buildout, as per usual." So you are expected to know a bit about buildout already. Earlier chapters may explain a bit more about this. The chapter then continues with a few very practical steps to take in the css and javascript registry when you want to support adding Rich Text or Date/Time fields on forms. Good to know.
Erik then takes you through your first steps with PloneFormGen, adding a FormFolder in the site and doing a bit of editing there. He presents all form fields that you can add. He explains that you should edit the default Mailer form action and set a recipient email address there, otherwise form submission will fail. When you add a Save Data Adapter, to store the submissions in the zodb, you get two valuable tips. Always keep a mailer adapter as backup in case something goes wrong and you lose the saved data; and do not remove or reorder fields when the form is already live, as the saved data will not get changed to fit.
The chapter gives a short recommendation on when to use PloneFormGen and when to create an Archetypes content type. Then it ends with giving you a taste of the flexibility of PloneFormGen. You can use it to create online tests for your students. You can use it to create a simple form (or a complex one if your organization needs that) as front end for creating news items (or other content items).
I'll write another review with a look at the other chapters later. If those chapters are similar to this one (and I have peeked already), then this looks like a very practical book. It presents clear goals, with step-by-step instructions to reach them, without magically sounding jargon, and with some hard earned wisdom so you can step around the common pitfalls. I think a lot of people could benefit from this.
Disclaimer: I got this book for free from Packt Publishing in exchange for a review; and ordering the book via one of the links in this article will land me some money.