Nidelven IT - All about Python, Zope & Plone - and Open Source!

Here you'll find issues related to our services. Mostly about Python, Zope and Plone, as well as hosting-related issues.

"Keeping IT real"

Older entries

Atom - Subscribe - Categories

Over 100000 downloads of my Python packages, Archetypes and the future

So, yesterday was a good day for me, programming-wise. The various PyPi packages I've created by myself have been downloaded over 100000 times.

I'm not sure exactly what to make of those statistics, but I think it's safe to guess that at least thousands of somewhat technical users have been using software I've developed lately.

You can see the statistics here:

Is this something to beat my chest about? Yes, I think so. Open Source projects rely on contributions from the community to thrive (most of the time anyway), and it is nice to be able to give something back and ensure the future of the project for the sake of jobs and users.

The most popular package is MegamanicEdit, a set of code and templates that enables creation of content type in an easier and more refactored way. Dexterity is the new thing in Plone and there's a lot of push to get it adopted, but I think there are also a lot of users of Plone out there that have invested in Archetypes-based solutions.. because of that I'm contemplating forking Archetypes or getting some sort of collaboration in the community to make sure that Archetypes-based code can still be used for a time to come, to basically say that we take care of users of Plone and think about compatability even for older software.

Another think is the license for Plone and its packages, but that discussion has been covered a bit on the mailing lists already, the question is how much work is required to make for example Archetypes more BSD-like so that one can sell off-the-shelf software for Plone as well.

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [19 Apr 14:12 GMT+2]

For the next ones, TinyMCE issues after installing another product

So, I've training a new guy to create new products from scratch, and in that process we encountered an issue with TinyMCE not working after Products.MenuNavigation 1.0a2 was installed.

The product was using the Extensions/ approach on a recent version of Plone 4. Things looked OK, but I could see the TinyMCE editor didn't display as it should. It rendered the textarea in HTML as it should with all the buttons and so on, but only a simple text area was displayed. To make things more interesting, using kupu instead as an editor fixed all problems.

After some debugging and cleaning up of unecessary code, I added profiles/default/metadata.xml, types.xml, types directory with MenuPage.xml and skins.xml. That worked.

So if you encounter something strange with TinyMCE after installing other products, check to see if the new product is using a proper GenericSetup approach, I guess this is the way forward anyway, unless you have a product that is spanning a wide number of Plone versions.

And roll back the transactions from the install new product point, I don't think reinstalling a product with a GS setup profile will fix TinyMCE once it has been broken.

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [21 Mar 14:24 GMT+2]

Getting up to speed with Active Directory, LDAP and Plone

So, we're going after a project that involves a lot of user management, and in that, Windows Active Directory and LDAP to authenticate against and update, so that when someone updates their info in Plone, the AD is also updated.

I haven't worked with a lot of Windows technology on the server side, it has almost always been Linux and other *nix variants.

So, to show that we are able to get things going with Active Directory, LDAP and Plone I figured I could setup VirtualBox on my Linux laptop, and install a trial version of Windows Server.

I downloaded Windows Server 2012, setup VirtualBox, booted from the ISO but the process stopped because the CPU I'm using is 32 (48) bit, and Windows Server 2012 requires 64 bit.

So OK, I googled again after Windows Server 32 bit and found the Windows Server 2008 trial ISO and downloaded that.

OK, so booting up the VirtualBox system with the ISO, getting to the install screen.. Windows asks for a product key but that shouldn't be necessary because I'm doing a trial..

To speed up the installation process I'm choosing the standard core server install.. which wasn't that smart, as the regular start menu and such were not available, just got a command prompt.. so back to the installer, install full standard version and we're up and running. :)

After some trying and failing I found that I could add all the necessary Active Directory bits through Administration tools -> Server Manager. OK, so got those installed, and setup a local DNS server.

Also installed Plone via the Enfold windows installer, as well as the Java JRE, so I could install Apache Directory Studio (which I opted to install after reading some nice things about it on the net).

OK, so after taking a break from this setup process I fired up VirtualBox again and couldn't get the network going. So, back to the Windows Server installation process, install Java, Plone, Active Directory again. This time, Active Directory was only setup with the LDAP module, so I worked with the simplest setup possible.

I tried some different configurations in buildout.cfg to get the package going, first issue was that python-ldap couldn't install properly so after some fiddling around I used the msi installer from PyPi and got python-ldap installed on \plone42\python.

OK, so far so good. But buildout still tried pulling and installing python-ldap.. after googling I found that the python-ldap's python directory moved to the buildout eggs folder fooled buildout to not download python-ldap. And after running buildout, I removed that folder so that there couldn't be any conflicts between the two info folders.

OK, so far so good.. tried firing up the instance and got the following error message:

ImportError: DLL load failed: The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log for more detail.

Googling I found that it was missing Visual C++ runtime libraries that were missing.. installing runtime libraries for 2005, 2008, 2010 and 2012 (2008 was the right one) that ImportError message disappeared.

So that went fairly well, but starting up with the instance.exe program again raised an ImportError, on win32file. So OK, I looked around and found pywin32 which should contain that module. Downloaded the installer, but didn't get far in the installation process as the Python that comes with the Plone installer doesn't register itself in the windows registry, and it isn't possible to set an installation path manually. So, OK, was about to copy over win32 modules from the new Python 2.6 installation but saw that win32 etc. were already in the site-packages of the Plone installation..

The plot thickens, and again after some Googling it seemed clear that the issue was starting the Plone instance with 'instance.exe fg' didn't work, while starting Plone through the services control panel would.

Well, well. I googled a bit about Enfold plone and finally figured out that there is some LDAP functionality included in the Enfold Plone Server Windows Installer, so I'm going to go for that. Going for server version 4.5 as it looks like the simplest thing to get installed and test how LDAP works with it.

OK, so I tried a bit of this and that, the point of this exercise was to test that it is possible to connect Plone to Active Directory, for retrieval and updating of data..

So, since I'm on a deadline, I decided to go for a simple, verifiable approach to managing AD content. Found pyad, installed Python 2.7, installed pywin32 using the installer, installed easy_install, used easy_install to install pyad. Also setup AD to run Domain Services.

Created the following script:


from pyad import pyad
import time


for attribute in user.get_allowed_attributes():
    if 'pass' in attribute.lower(): print attribute

print 'old password', user.get_attribute('userPassword')[0][:]
user.update_attribute('userPassword', 'newPassword-' + str(time.time()))

print 'new password', user.get_attribute('userPassword')[0][:]


And that worked well. It is nice to know that there is a rather uncomplicated way to get access to AD, using Python.

I see that what was Enfold Server will be Open Source, and the plan is to get a proper Plone system integrated with Active Directory in the way most people do, but a simple fallback as described above is nice to have. It would be nice if someone wrote a thorough tutorial or manual on how to integrate Plone with AD, as AD seems to be the choice a lot of organizations use to manage users, access, software licenses and other information.

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [06 Mar 16:02 GMT+2]

Something that slowed me down a bit today - TinyMCE + old skin

So I got an email from a customer today, having problems with editing news articles and other HTML-content on their site. HTML content was only displayed in a text area, even though the personal settings and plone site were setup to use TinyMCE.

They were upgraded from a prior version that wasn't using TinyMCE as the default editor, so I thought something might be wrong there..

After some work, testing and so on, I finally figured out that the issue was the skin settings in portal_skins - the tinymce folder was listed way below the plone_wysiwyg folder, and then the HTML-code for the editor in the text area was fetched from Plone default, and not TinyMCE.

Pressing customize on the tinymce/wysiwyg_editor template (or something similar) and putting it in the active theme custom folder did the trick, from then on TinyMCE worked well.

Just a tip for the weekend, have a good one. :)

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [01 Mar 17:34 GMT+2]

Company website upgrade & update, now and then

So, I'm pretty much done with the upgrade of the website

It's been a bit of work to fine-tune the layout, polish the content (although it should be more). I've also had to go in and modify the package to include the suggested patch (don't remember where) that skips <ul> tags in navigation to get an HXTML result that is 100% compliant with the W3C validator.

I started with the beyondskins.responsive theme for layout and design, and have made a lot of changes to it to simplify it, and make it pass the W3C validator. It had some weird HTML-attributes such as role.

There was also an HTML attribute in Plone that didn't jive with the W3C validator, and that was the attribute placeholder on the search box. Isn't (X)HTML compliance a bit important thing for SEO and accessibility, if so - why did something like that slip through the Plone development/release process?

I tested the webpage in a speed tester for counting downloads, download speed and so on. There was a *huge* amount of Javascript included, so I figured I could make Javascript files available only for logged inn users in portal_javascripts.. that worked out well and cut down a big chunk of requests and data transfer. I did the same for portal_kss. Although now I see the search option isn't available for users with a small screen size (probably Javascript) but that'll be fixed.

There was one thing in particular I noticed when validating the page on W3C - and that was that the KSS system put an invalid attribute into the template. So I added a product in products called Patches, with the following file:

from zope.interface import implements
from zope.component import getMultiAdapter
from zope.viewlet.interfaces import IViewlet

from Products.Five.browser import BrowserView

class KSSBaseUrlViewlet(BrowserView):
    """ Renders a link rel tag with the real url of the published object. """

    def __init__(self, context, request, view, manager):
        super(KSSBaseUrlViewlet, self).__init__(context, request)
        self.__parent__ = view
        self.context = context
        self.request = request
        self.view = view
        self.manager = manager
        self.context_state = getMultiAdapter((context, request), name=u'plone_context_state')

    def update(self):

    def render(self):
        # We need to generate the link in every case, since the new url base detection
        # algorithm of kss relies on it.
        return u'<link rel="alternate" href="%s/" />' % self.context_state.object_url()

from import headerviewlet

headerviewlet.KSSBaseUrlViewlet = KSSBaseUrlViewlet

That worked out well.

Anyway, I think the website looks pretty good now, available in English, Norwegian (y un poco) espaƱol.

I would *love* to get some comments and feedback on what is good and bad, what should be changed, removed or added.

Thanks :)

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [10 Jan 12:09 GMT+2]

Company website upgrade, day 3.5

I decided that today I was going to launch the site, regardless of small bugs that still were present.

The responsive skin suited us well, but I had to make some final adjustments. I decided the big header image could be dropped from screens that were < 768 pixels wide in styles.css and that the footer info could be dropped from the theme index.html (it has a sharp dark blue) and the page would look cleaner that way.

So far so good.

We had been working on the Webshop in parallel with this, refactoring and moving HTML-y stuff out to templates, and those templates were missing the i18n:domain attribute. So, OK, I have to update some templates with a domain setting for translations. Did that, checked the webshop and nothing. After some thinking and fiddling with styles etc. I remembered it could be compiling the translations files - as nothing else was getting translated as well.

Well, things weren't heavily tested, so I decided to just launch the thing and stick a "(Beta)" besides the logo.

After removing the footer, proper credit to Simples Consultoria wasn't given, so I added an about (om in Norwegian) page for the website where they are credited, as well as some actions which are shown in the upper right corner for contact, about the webpage etc.

Voila, site launched. Have a look at using your computer or any other device. Looks pretty good doesn't it? :)

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [21 Dec 14:05 GMT+2]

Company website upgrade, day 2&3

So, today I continue on upgrading our company website. We have an internally developed product for simple "page" management, you can add pages, within that page add new pages, images or files. That product will probably released sooner rather than later BTW, probably under the Products.CustomPages name.

Working with the pages product raised the following traceback:

2012-12-19 13:05:03 ERROR portlets Error while determining renderer availability of portlet ('context' '/shared/cop/nidelven/plone' u'navigation'): Object pa-norsk was not found
Traceback (most recent call last):
  File "/home/nitwww/plone/instance/buildout-cache/eggs/plone.portlets-2.1-py2.7.egg/plone/portlets/", line 117, in _lazyLoadPortlets
    isAvailable = renderer.available
  File "/home/nitwww/plone/instance/buildout-cache/eggs/", line 135, in available
    tree = self.getNavTree()
  File "/home/nitwww/plone/instance/buildout-cache/eggs/plone.memoize-1.1.1-py2.7.egg/plone/memoize/", line 51, in memogetter
    val=func(*args, **kwargs)
  File "/home/nitwww/plone/instance/buildout-cache/eggs/", line 204, in getNavTree
    return buildFolderTree(context, obj=context, query=queryBuilder(), strategy=strategy)
  File "/home/nitwww/plone/instance/buildout-cache/eggs/", line 186, in buildFolderTree
    results = portal_catalog.searchResults(query)
  File "/home/nitwww/plone/instance/buildout-cache/eggs/Products.LinguaPlone-4.1.2-py2.7.egg/Products/LinguaPlone/", line 34, in searchResults
    return self.__lp_old_searchResults(REQUEST, **kw)
  File "/home/nitwww/plone/instance/buildout-cache/eggs/Products.CMFPlone-", line 428, in searchResults
    return ZCatalog.searchResults(self, REQUEST, **kw)
  File "/home/nitwww/plone/instance/buildout-cache/eggs/Products.ZCatalog-2.13.23-py2.7.egg/Products/ZCatalog/", line 604, in searchResults
    return self._catalog.searchResults(REQUEST, used, **kw)
  File "/home/nitwww/plone/instance/buildout-cache/eggs/Products.ZCatalog-2.13.23-py2.7.egg/Products/ZCatalog/", line 907, in searchResults
    return, sort_index, reverse, sort_limit, _merge)
  File "/home/nitwww/plone/instance/buildout-cache/eggs/Products.ZCatalog-2.13.23-py2.7.egg/Products/ZCatalog/", line 656, in search
  File "/home/nitwww/plone/instance/buildout-cache/eggs/Products.ZCatalog-2.13.23-py2.7.egg/Products/ZCatalog/", line 676, in sortResults
    index_key_map = sort_index.documentToKeyMap()
  File "/home/nitwww/plone/instance/buildout-cache/eggs/", line 104, in documentToKeyMap
    pos[rid] = container.getObjectPosition(id)
  File "/home/nitwww/plone/instance/buildout-cache/eggs/Products.Archetypes-1.8.3-py2.7.egg/Products/Archetypes/", line 56, in getObjectPosition
    raise NotFound, 'Object %s was not found' % str(id)
NotFound: Object pa-norsk was not found

This error occurred after I changed the language from Neutral to Norwegian - so as I thought, a portal_catalog clear and reindex operation fixed that issue.

On to day 3.. been trying different themes and it is easy to mess up things, but found, finally, that beyondsskins.responsive could be used. Spent a bit of the day tracking down a bug where portlets were rendered downwards in the middle of the page, and tracked that back to malformed HTML that somehow got past the HTML-parsing engine.

Worked a bit on the Products.CustomPages product (not published yet), putting it into an egg directory structure and adding some features.

So, back to theming. The responsive skin is nice, but the columns weren't covering the whole page as they should. Tried setting width for columns in the responsive CSS - that didn't work. Looked through the HTML code, and found that a CSS file from the drupal theme was referenced. Scratched my head a bit about that one on how to remove it and thought "Aha!" - I can just remove it from the entire setup (using buildout).

I have used the responsive skin earlier when I needed a quick fix for my soccer team. One of the changes made there was that I converted the header image from png to jpg and chose a relatively low quality - making the page much faster to load.

So here I was looking on that the design and that the logo is too small. Yesterday I was working with the Drupal theme, but now I needed a somewhat bigger logo. So I did an undo on the logo.png file, downloaded it into the static theme folder on the FS, adjusted the bg.jpg in the responsive package to blend the colors better with the header (using GIMP, background and radient fill - taking the color from the edge of the header image), and then undid the undo on logo.jpg to have that ready for the Drupal theme.

OK. That's enough I think, time to relax a bit after working hard. :)

Stay tuned for the continued upgrade saga. [;]

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [19 Dec 11:30 GMT+2]

Company website upgrade, day 1

So, I've been wanting to upgrade our website ( ) for a good while now. The biggest thing holding us back has been the webshop we've developed interally and sell - but that has gotten a lot of new stuff as well as fixes and clean ups, so it is about ready to go for production.

So I setup a new site from the unified installer package, worked a bit on the webshop and separating it from older, legacy python eggs and code - installed the latest hotfix and got that working.

Went into the ZMI and hit the Plone upgrade button - it went by fast and voila the site was upgraded.

However, we're now going to use LinguaPlone with the webshop and the website so that was installed too and things seem fine.

But, wherever I went in the site I got strange tracebacks like this:

Traceback (innermost last):
Module ZPublisher.Publish, line 126, in publish
Module ZPublisher.mapply, line 77, in mapply
Module ZPublisher.Publish, line 46, in call_object
Module Shared.DC.Scripts.Bindings, line 322, in __call__
Module Products.PloneHotfix20121106.python_scripts, line 63, in _patched_bindAndExec
Module Shared.DC.Scripts.Bindings, line 359, in _bindAndExec
Module Products.CMFCore.FSPageTemplate, line 237, in _exec
Module Products.CMFCore.FSPageTemplate, line 177, in pt_render
Module Products.PageTemplates.PageTemplate, line 79, in pt_render
Module zope.pagetemplate.pagetemplate, line 113, in pt_render
- Warning: Macro expansion failed
- Warning: <type 'exceptions.AttributeError'>: Macro widgets/rich does not exist for <ATDocument at index_html>
Module Products.PageTemplates.ZRPythonExpr, line 48, in __call__
- __traceback_info__: context.widget('text', mode='view')
Module PythonExpr, line 1, in <expression>
Module Products.Archetypes.BaseObject, line 287, in widget
Module Products.Archetypes.Renderer, line 26, in render
Module Products.Archetypes.generator.widget, line 147, in __call__
AttributeError: Macro widgets/rich does not exist for <ATDocument at index_html>

as well as

Module ZPublisher.Publish, line 126, in publish
Module ZPublisher.mapply, line 77, in mapply
Module ZPublisher.Publish, line 46, in call_object
Module Products.CMFFormController.FSControllerPageTemplate, line 91, in __call__
Module Products.CMFFormController.BaseControllerPageTemplate, line 31, in _call
Module Shared.DC.Scripts.Bindings, line 322, in __call__
Module Products.PloneHotfix20121106.python_scripts, line 63, in _patched_bindAndExec
Module Shared.DC.Scripts.Bindings, line 359, in _bindAndExec
Module Products.CMFCore.FSPageTemplate, line 237, in _exec
Module Products.CMFCore.FSPageTemplate, line 177, in pt_render
Module Products.PageTemplates.PageTemplate, line 79, in pt_render
Module zope.pagetemplate.pagetemplate, line 113, in pt_render
- Warning: Macro expansion failed
- Warning: <type 'exceptions.AttributeError'>: base_edit
Module zope.tal.talinterpreter, line 271, in __call__
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 867, in do_useMacro
Module zope.tales.tales, line 696, in evaluate
<Products.CMFFormController.ControllerState.ControllerState object at 0xdcd6b6c>},
'repeat': <Products.PageTemplates.Expressions.SafeMapping object at 0xe2fb34c>,
'request': <HTTPRequest, URL
'root': <Application at >,
'template': <FSControllerPageTemplate at /shared/cop/nidelven/plone/atct_edit used for /shared/cop/nidelven/plone/index_html>,
'traverse_subpath': [],
'user': <PropertiedUser 'morphex'>}
Module zope.tales.expressions, line 217, in __call__
Module Products.PageTemplates.Expressions, line 147, in _eval
Module zope.tales.expressions, line 124, in _eval
Module Products.PageTemplates.Expressions, line 74, in boboAwareZopeTraverse
Module OFS.Traversable, line 317, in restrictedTraverse
Module OFS.Traversable, line 285, in unrestrictedTraverse
- __traceback_info__: ([], 'base_edit')
AttributeError: base_edit

Now, at first it was hard to get what the issue was, but when the AttributeError base_edit popped up, I got an idea of where to start.

I had a look in


and found that archetypes, archetypes_kss etc. were all in the different skin configurations so I scratched my head a bit. Well, it turns out that somewhere along the way, the portal_skins/archetypes folder went missing.. So I added a Filesystem directory view in the portal_skins folder and selected the archetypes folder and now things are just fine and dandy.

So, proceeding with the upgrade. I was still getting some weird errors, and decided to do a clear and rebuild of portal_catalog. However, when I got to portal_catalog and tried to update it, various AttributeError exceptions on the attribute clear in ZCatalog were raised. I googled a bit about it and saw suggestions that it could be because of the theme (...) but figured I could copy a portal_catalog from a fresh Plone site instead and delete the one that was failing.

That worked, I now had a working, updated ZCatalog portal_catalog..

So, onwards and upwards. Or so I thought. :)

A new error was raised whenever I tried to switch between languages:

  Module Products.CMFPlone.browser.ploneview, line 295, in have_portlets
  Module, line 73, in have_portlets
  Module plone.portlets.manager, line 48, in visible
  Module plone.portlets.manager, line 67, in portletsToShow
  Module plone.portlets.manager, line 70, in allPortlets
  Module plone.memoize.view, line 47, in memogetter
  Module plone.portlets.manager, line 107, in _lazyLoadPortlets
  Module plone.portlets.retriever, line 62, in getPortlets
  Module, line 40, in globalPortletCategories
  Module, line 94, in _getContentType
  Module Shared.DC.Scripts.Bindings, line 193, in __getattr__
Unauthorized: You are not allowed to access 'getTypeInfo' in this context

After some headscratching and looking deep into the portletcontext code and looking that the portal_workflow , I finally figured out that the reason for the failure was that the page I wanted in a different language was in a draft state, and not published (publish would give access to the getTypeInfo method via Access Contents Information in LinguaPlone).

OK, so far so good. That's it for today, will blog later. :)

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [18 Dec 14:02 GMT+2]

2 new products released, PloneboardComments and CalendarListingPortlet

So, I released some new products to the Plone community the last couple of weeks. These are products we've been using a while internally and I found that now was a good time to release these publicly.

The first is called Products.PloneboardComments, and it is a product that replaces the default discussion system in Plone in favor of Ploneboard. When configured with a PloneboardComments object, it will override the folder it lies in and any subobjects of that folder, making these objects discussable in a configured forum.

It is located here:

The second is CalendarListingPortlet, I think we wrote this a long time ago when we needed some specific listing (internally published events) in an intranet, it is still in use and working today. A simple little thing that will probably become more user-configurable in the future.

And that's located here:

Enjoy, and please do send feedback :)

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [22 Oct 14:07 GMT+2]

New releases of MegamanicEdit and Products.MegamanicEditContentTypes

Today new releases of these packages were made. A very small but significant change to MegamanicEditContentTypes, phone numbers now have a separate field for country prefix and eventually this will be a drop-down list or something similar for ease of use.

Two changes to MegamanicEdit are noteworthy, one is that adding objects using megamanic_add now correctly handles erroneous input, and a patch is also made to the Archetypes framework so that the standard view of objects only displays fields with a value set.

The packages can, as always, be found here

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [08 Oct 18:17 GMT+2]

collective.easyslider and AttributeError: 'NoneType' object has no attribute 'getData'

I installed collective.easyslider on a new site and things were looking good. But when somebody started adding slides to the slider, an AttributeError: 'NoneType' object has no attribute 'getData' popped up.

I looked at the logs and they didn't tell anything, so I had to manually start putting print statements in the PortalTransforms convertTo method to see what was going on. And then pdb.set_trace() when the offending part of the code was found.

Turns out that a mime type was missing in the mimetypes registry, adding a mime type with the id safe-html and the mime types text/x-html-safe fixed everything.

Strange that the error messages didn't display, but oh well.

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [10 Aug 10:26 GMT+2]

Products.SimpleCalendar - new (but yet old) accessible calendar for Plone

As this week started I was working on upgrading a website for a customer, a site which had been using p4a.plonecalendar for quite a while, and doing that well..

But the site is in a (big) upgrade process, and p4a.plonecalendar and its dependencies created a bit of a mess and the package hasn't had a release in a couple of years, so I decided to create a new calendar package that uses dateable.* libraries to do most of the work.

The process for creating the package was interesting, I had to dabble a bit with adapters for example, as well as finding good ways of dealing with the dateable code which uses Python's datetime module instead of Zope's (so conversion tools were used to convert to Python's datetime). There are also some interdependencies between dateable and some p4a.* packages, so a couple of the p4a packages are included in the dependencies for Products.SimpleCalendar as well.

The main reason I wanted to use the dateable libraries was that I saw p4a.plonecalendar was not a lot of code and that most of the work seemed to be done in dateable as well as that we have a customer that does need an accessible website (internet, intranet, extranet) and accessible tools in that website. And dateable (correctly) uses a table to layout and give semantic meaning to the calendar display. It also doesn't hurt to have a bit of control over the code, I think we'll use this calendaring solution on projects to come as well.

The release now is an alpha-2, but I think it is good enough to use, at least play with until a beta and then a final release.

(By the way, you can expect some bells and whistles when it comes to the selection of events to be displayed in the calendar as well). Right now it can filter events for display on object state (private, internal, published and so on).

You can get the package here:

[Updated to please the POP crowd]

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [02 Aug 08:34 GMT+2]

Making PatchPloneContent play nicely with blobs

So I'm upgrading this old site that has iw.fss as the storage system for blob content and was struggling a while with some content not having all their Archetypes schema content transferred during a Plone upgrade.

The code seemed fine and I couldn't find a problem so the debugger was brought out to look at what was going on with certain types of content.

It turns out the issue is rather simple, the product I'm using to patch content types with extra schema fields (Products.PatchPloneContent) doesn't include ATBlob as a content type (...)

There is something to be said about keeping things in one place, but it was probably all good intentions when the blob content type was put in the package instead of inside ATContentTypes. Anyway, the fix was simple:

    from import ATBlob
    content_classes = (
except ImportError:
    content_classes = (

That code should work for Plone 4 and 3 as well, and now the rather simple PatchPloneContent product has proper support for blobs as well.

Updated to strip invalid feed code. [Later.. Update 2 to please the POP crowd]

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [26 Jul 14:29 GMT+2]

New releases of MegamanicEdit and Products.MegamanicEditContentTypes

I (wisely) made a new beta release of these two products today. There are some minor feature enhancements such as messages to the user creating the objects that they must publish content if anonymous users should be able to submit content.

There were also some bugfixes, a user error (presumably) had me "fixing" the table listing of added objects for the 2.0.6 release of MegamanicEdit, then I found that megamanic_listing should be reversed to 2.0.5 again as things were working as they should.

So, here are the releases:

I feel pretty good about these and that things are crystallizing so watch out for more good stuff. :)

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [14 Jun 15:26 GMT+2]

Some accessibility improvements, ScreenReaderNavigation

A while ago I posted this PLIP on

Which suggests changing a fair bit of the layout of Plone, to make it more accessible. Today I released Products.ScreenReaderNavigation which overrides the standard navigation portlet to give start and end headers so that users of braille for example can easily find the navigation portlet within everything that is on a standard Plone page.

It is here:

The customer has quite a big site and there are many enhancements done to improve its accessibility for visually impaired (among others) users. I've learned that there are quite a bit of things to think about for handicapped users, for example that a user only has one hand, is deaf or has any combination of different things that impairs their use of what many consider standard web features.

Anyway, this product is a step in the right direction, and it really is good to enable everyone to participate so that people of all walks are included in what most people take for granted.

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [06 Jun 15:41 GMT+2]

Products.BlobNewsItem - strange issues and new release

I was working on Products.BlobNewsItem before the weekend as I was bumping into strange issues that made the image blob field not display on editing and viewing of the newsitem content type.

After some back and forth, looking around I found a pretty decent solution to the issue.. after putting some print statements in Archetypes I found that the field wasn't writeable, and looking further down, the accessor and mutator properties and methods weren't being set for the ImageField.

Well, I put this code in there:

class MyBlob:
\tsecurity = ClassSecurityInfo()

\tsecurity.declareProtected(ModifyPortalContent, 'setImage')
\tdef setImage(self, *arguments, **keywords):
\t\tfield = self.getField('image')
\t\tfield.set(self, *arguments, **keywords)

\tsecurity.declareProtected(ModifyPortalContent, 'getImage')
\tdef getImage(self, *arguments, **keywords):
\t\tfield = self.getField('image')
\t\treturn field.get(self, *arguments, **keywords) =
newsitem.ATNewsItem.setImage = MyBlob.setImage.im_func
newsitem.ATNewsItem.getImage = MyBlob.getImage.im_func


as well as


in the ImageField and that does the trick. Why this issue popped up I don't know, but at least there's a pretty easy way to fix it.

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [04 Jun 08:18 GMT+2]

Updates to MegamanicEdit and Products.MegamanicEditContentTypes

So I released a new version of MegamanicEditContentTypes again today, as a customer needs it for a somewhat urgent project.

The changes in the latest release were

Making email messages "protected" by default.
Adding search form and mailing form for contacts.
Improving generation of Email message sender info
Fixing up some permission settings

Which basically means that email messages are taken out of any regular workflow and its View permissions set to the roles Owner and Manager.

The whole contact thing needed a search form as well, so I created one where the results page can be used to create an email message.

I also found that the permission settings on some content classes were too widely set (public) and restricted these to a user with a View permission.

Not any really big visual changes, but the contact search page should make this product a more attractive contact database / mailing solution.

One more note as well: one should enable member areas, as that folder will get an emails folder with all emails sent from that user.

[Later.. update to fix feed bugs]

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [14 May 12:11 GMT+2]

An event with extended attendee handling, updates to ME and MECT

So the last week or so I've been working on a customers' wishes to have an event that professionals in their field could sign up for.

Some years ago I created a modified version of the regular Event type in Plone which could accept attendees, but found that it would probably be easier (and cooler) to develop this system to depend on the MegamanicEdit package.

So I ended up adding some new code to MegamanicEdit which makes the Contact landing page (which is used in AttendeeEvent) accept some more setup info as well as looking outside (above) itself to see if there are any limitations on how many objects can be added (event visitors registered).

The whole attendee event thing works well, it's a bit rough around the edges (unpolished) but should serve the goal of lessening the administrative burden for the customer.

There is also a feature in MegamanicEdit that many might not be aware of, and that is that you can (in a contact landing page object which uses the ME template system) specify which fields should be required, and which fields should be displayed in a listing of those who have registered.

So with a Ctrl-click on the tabular listing one can easily copy over data from registered users. There is a half-baked export to CSV feature in MegamanicEdit as well, but for now the Ctrl-click should suffice.

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [07 May 11:33 GMT+2]

Products.MegamanicEditContentTypes - a new content class group

So MegamanicEdit has been a pet project of mine for a while, and today I made another release of it.

I've also been working to create a unified "content class" package for different content (such as what used to be in the GrailTact package)..

So now there is a package, and it is available here:

It contains contact, contact landing page, email and various small content classes such as email address. My hope is that this project will grow, and with the technical foundation in MegamanicEdit which uses Archetypes there is a lot of potential. [:)

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [26 Apr 13:35 GMT+2]

Products.RFC822AddressFieldValidator - A sparse beginning

So I released a new product a little while ago, Products.RFC822AddressFieldValidator. It's a validator that checks if the entered data corresponds to a proper mail address field such as To, CC etc. of an email message.

It is very simple at the moment, taking a comma as an address separator and checks if @ is in every of those adresses. I was thinking of using the builtin Archetypes/Plone email validator to check each email address, but wasn't sure exactly what constituted validation as I'm not sure what is returned on valid result (one would think it is something that can evaluate to True..). Which is kind of funny when I think about it.

Anyway, here is the product

It'll be a dependency with Products.MegamanicEditContentTypes which has an email message class for sending out messages from within Plone.

[Later: updated to fix feed errors]

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [25 Apr 12:07 GMT+2]

Products.NewsPage - for powerusers

So I released Products.NewsPage to PyPi a little while ago. The story of this product is that we had a customer that wanted some customizations in the way news items were displayed, such as being able to pin a news items to one of the 3 first spots in the news listing.

A custom index_html page template was also created, and some macros were added to the NewsPage product so that one could embed news listings within a page template with custom layout.

The egg is here:

And is among other things used together with Products.StickyList to create a custom frontpage that our customer can easily update and customize.

It's a nice example of how one can hand off control of the website to the customer, giving them more value and bang for the buck.

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [23 Apr 09:36 GMT+2]

Working on a simple mailing package + MegamanicEdit Content Types and GrailTact

Hoi. So some of you might have been following my various Plone-related packages such as GrailTact & MegamanicEdit.

Well, there are some things in development now, and the content types in GrailTact are being moved to a product called Products.MegamanicEditContentTypes..

This is to refactor and generalize the modules as much as possible, as well as building a common archive of content types that can be easily used by many without repeating work here and there.

It's been a while since I've done a lot of work on these packages, and I found I was using Plone 3.3.5 and had to make some adaptations for that when creating a validator that can validate that one or more email addresses were correctly formatted for an email message..

So I ended up adding a hook at the bottom of the new validator which tries to use classImplements and handles it if an exception is raised.

I see the general trend for various Plone projects is to stay working with the most recent version of Plone, which is fine, but I think the right thing for my projects is to span two major versions, I'll see how much work and if it is worth it in the long run.

While working with the email sending application I found that the Python 2.4 version didn't have the most recent version, and that 2.5 or above did, so I ended up backporting that email package as you can read about here:

It was fun, and I think the first pure Python project I've created in a while, at least registered on PyPi.

As you can see I'm getting a bigger list of modules here:

Which is cool, it is very motivating that people are using things I've created; I think the code is pretty decent and that people find it usable is cool.

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [12 Apr 17:36 GMT+2]

A little about Products.EnhancedNewsItemImage

So a little while ago I released that product onto PyPi:

After having used that set of code in production for some years. We developed it initially for two reasons, one was that captions were needed on all images as we were building a site for an organization for visually impaired users..

In the same go, we found that we could probably save some space and work/time on making it possible to select images already added on the site (IIRC it was a customer request).

So this package does those two things fairly well, it enables different sources for an image, and it always asks for an image caption, if an image has been set.

Now this is another package to blog about, but I haven't gotten too much response from these packages, thinking on the upside, I think that must be because they work. Would be nice to get an email ( from people who use it though. :)

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [30 Mar 17:02 GMT+2]


So we released Products.ForumPage a little while ago on PyPi:

It's a nice little product (content-type) that enables displaying contents of several forums on one page. It was developed primarily for a customers' intranet, where user activity and access to that activity was deemed important.

It's not that advanced, but it does the job well. While editing you select which forums to list posts from and then they become available on the ForumPage view. This view can be set as the standard view for some part of the site and is then displayed to the users.

Useful in other words to improve the coherence of a group.

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [29 Mar 11:27 GMT+2]

Page Templates slots - Necessity is the mother of invention

So I've been upgrading customers' Plone sites the last couple of months, and one thing I encountered is that there are changes in the main_template, where there is a new content-core slot.

It changes things a lot for existing templates, as content that uses the content-core slot were not getting a page header title (<h1>).

So, I browsed around in the zope.tal, zope.tales and zope.pagetemplate modules and in the process found defer: and lazy: - which were interesting and I gave those a go but didn't get it working properly.

I thought the standard template variable would be the right place to look, and it turned out to be right. Doing a pprint of the dictionary of the template variable gave a hit for fillSlots..

So, I packaged up some (very loosely tested) python code for getting the currently used slots here:

And it works well. With this installed you can run for example 'python:"content-core" in template.pt_filled_slots()' from within a template to see which slots the calling template is using.

Extremely useful to get around the content-core issue, and maybe it makes for some flexible, compact or clever constellations of macros in Zope's page templates.

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [22 Mar 12:04 GMT+2]

All about contacts and multiediting

So, last week I made a release of GrailTact and MegamanicEdit, two tools used to manage contacts and make structured editing of objects easier.

GrailTact is a contact database in its own right, and long-term the plan is to create the best contact database / address book available for Plone, with syncing towards GMail, Facebook and so on.

About 10 years ago I worked on a framework somewhat similar to Archetypes, called Warp Framework. So I have some experience with those kinds of frameworks.. MegamanicEdit is an add-on to Archetypes that enables breaking up the usual way of using Archetypes, that is, by making many small classes and a main content type, so for example a Contact class object can have multiple Email subobjects, and through MegamanicEdit one can edit all of these objects at once, through the MegamanicEdit edit view.

I think with a good collection of different simple content classes, such as for example Email address with the fields Email and Description, creating and managing Archetypes projects can be easier and more productive than they have been so far.

A limitation of MegamanicEdit is that it is only tested with a few types of fields and widgets, so longer term it should explicitly support for example HTML (text) fields as well.

You can see the two egg packages here:

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [19 Mar 07:23 GMT+2]

If they're serious about standards..

So, today after some debate I had to deal with Internet Explorer and a Javascript image rotator that didn't work as it should in IE 9.

The site is somewhat old, so I tried different X-UA-Compatible headers..

After trying different settings, main_template has been customized and modified to include a junk define statement which sets the HTTP response header

<html xmlns="
      tal:define="lang language; xyz python:request.RESPONSE.setHeader('X-UA-Compatible', 'IE=edge')"

and things work swimmingly well. I tried looking at the jquery package (this is a rather old setup) and it was 1.1.2. Bumping it to 1.1.4 did not fix anything.

The MS docs explicitly says that edge mode shouldn't be used in anything but testing, but it does the trick here.. and when I think about it, IE should have two "edge" modes, "edge" and "bleedingedge". Why you say? Because browsers these days update rapidly, and bleedingedge could be considered alpha - until browser makers *together* find a "contract" on how an HTML, Javascript or CSS element should behave. That way we can avoid further fragmentation of how standards are implemented.

I don't know how this works with other browsers, but seems obvious to me that this is a good way to deal with standards-in-motion and frequent browser updates.

If that doesn't work, then some common HTML/Javascript/CSS library which bridges the gap between implementations will be sorely needed, and maybe that's how it will end up in the end.

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [15 Mar 13:07 GMT+2]

Automating Plone setups - Faking a Zope user

So I've setup our Plone demo site,

again after a long hiatus. It includes a script to setup Plone instances automatically as users register with their email address.

In that process I discovered that the Plone installation (setup) scripts stopped working properly if an unauthenticated user was running the External Method that sets up the sites (workflowexception, no action for object).

After a little thinking I figured that the problem might be the login status of the user registering as the registration was working fine when being run by the admin (logged-in) user.

So I created this script:

Which overrides the standard security context and enables one to fake a Zope user from an acl_users folder, or simply fake a system user such as system or nobody.

The product won't change the actual logged-in (or anonymous user) for example when looking at the undo tab, but it does the trick for the workflow machinery which accepts whatever user you select or specify when calling FakeZopeUser.FakeUser.

[Update, demo site now works as it should, so try again if it didn't]

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [05 Mar 09:33 GMT+2]

Plone news items with blob storage!

So, we've had a customer running iw.fss for a while (has quite a bit of data and usage) and now we're moving them off it and onto

In that process I managed to pack up the News Item patch into a product, so that others can start new sites with a patched storage.

The patched field is a verbatim copy of what's already in's schema, except that it makes use of's ImageField for storage.

Here it is:

Migrating existing news items to new storage is left as an exercise to the reader (hint: look at

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [28 Feb 10:37 GMT+2]

Clearing out an old mess the backwards way

Lately I've spent quite some time tearing out old Plone 4 Artists (p4a) and dateable dependencies from a Plone site upgraded from Plone 3 to Plone 4.

Somewhere in the process I found that p4a.plonecalendar in more recent versions had an uninstallation method, but I doubt that it by itself would be able to remove everything from the various places it had lodged itself.

It was a bit stressful as the project was given a quote assuming that things were going to do OK, and this thing ate up hours and days as I poked through the ZODB, zope.interface and zope.components code and added hooks to see what was going on.

In the process I managed to repackage most of the work into two Python eggs:

Two nice eggs to "stabilize" a site that has problems because of broken packages and their broken interfaces. It's actually a bit fun to look back at it now, and I can pat myself on the back for creating two a bit obscure but powerful packages. :)

[Permalink] [By morphex] [Python, Zope, Plone - and anything loosely related to that (Atom feed)] [17 Feb 11:21 GMT+2]