Planeta Plone

Acesta este locul unde dezvoltatorii și integratorii scriu despre Plone, precum și cea mai bună sursă de știri și noutăți din comunitate.

March 14, 2013

Nidelven IT: 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.
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.

David "Pigeonflight" Bain: How to install Plone Social Suite

by David Bain at 2013-03-14T05:07:41Z

Here's my quick recipe to get started with Plone Social Suite. Plan to spend about 15 minutes. As usual this does not assume any Plone knowledge, just the ability to follow a few instructions and the assumption that you have a Dotcloud and Cloud9 IDE account. I've used Dotcloud and Cloud9 ide in the past to get Plone installed. This short recipe demonstrates how to customize your Plone setup at

Mikko Ohtamaa: Ultimate Python colorized logger: Somewhere over the rainbow

by Mikko Ohtamaa at 2013-03-14T04:41:45Z

To make logging based debugging and diagnostics more fun, I created the following enhanced Python logging solution. It colorizes and adjusts logging output so that one can work more efficiently with long log transcripts in a local terminal. It’s based on logutils package by Vinay Sajip.

Screen Shot 2013-03-14 at 6.04.36 AM

What it does

  • Targets debugging and diagnostics use cases, not log file writing use cases
  • Detects if you are running a real terminal or logging to a file stream
  • Set ups a custom log handler which colorizes parts of the messages differently
  • Works on UNIX or Windows

Example of a longer terminal logging transcript which does a lot of output in logging.DEBUG level:

Screen Shot 2013-03-14 at 6.10.39 AM

The source code and usage examples below.

1. Further ideas

How to make your life even more easier in Python logging

  • Make this to a proper package or merge with logutils
  • Use terminal info to indent message lines properly, so that 2+ lines indent themselves below the starting line and don’t break the column structure (how to get terminal width in Python?)
  • Make Python logging to store full qualified name to the function, instead of just module/func pair which is useless in bigger projects
  • Make tracebacks clickable in iTerm 2. iTerm 2 link click handler has regex support, but does not know about Python tracebacks and would need patch in iTerm 2

Please post your own ideas :)

2. The code

Source code (also on Gist) – for source code colored version see the original blog post:

# -*- coding: utf-8 -*-
    Python logging tuned to extreme.
__author__ = "Mikko Ohtamaa <>"
__license__ = "MIT"
import logging
from logutils.colorize import ColorizingStreamHandler
class RainbowLoggingHandler(ColorizingStreamHandler):
    """ A colorful logging handler optimized for terminal debugging aestetichs.
    - Designed for diagnosis and debug mode output - not for disk logs
    - Highlight the content of logging message in more readable manner
    - Show function and line, so you can trace where your logging messages
      are coming from
    - Keep timestamp compact
    - Extra module/function output for traceability
    The class provide few options as member variables you
    would might want to customize after instiating the handler.
    # Define color for message payload
    level_map = {
        logging.DEBUG: (None, 'cyan', False),
        logging.INFO: (None, 'white', False),
        logging.WARNING: (None, 'yellow', True),
        logging.ERROR: (None, 'red', True),
        logging.CRITICAL: ('red', 'white', True),
    date_format = "%H:%m:%S"
    #: How many characters reserve to function name logging
    who_padding = 22
    #: Show logger name
    show_name = True
    def get_color(self, fg=None, bg=None, bold=False):
        Construct a terminal color code
        :param fg: Symbolic name of foreground color
        :param bg: Symbolic name of background color
        :param bold: Brightness bit
        params = []
        if bg in self.color_map:
            params.append(str(self.color_map[bg] + 40))
        if fg in self.color_map:
            params.append(str(self.color_map[fg] + 30))
        if bold:
        color_code = ''.join((self.csi, ';'.join(params), 'm'))
        return color_code
    def colorize(self, record):
        Get a special format string with ASCII color codes.
        # Dynamic message color based on logging level
        if record.levelno in self.level_map:
            fg, bg, bold = self.level_map[record.levelno]
            # Defaults
            bg = None
            fg = "white"
            bold = False
        # Magician's hat
        template = [
            self.get_color("black", None, True),
            "] ",
            self.get_color("white", None, True) if self.show_name else "",
            "%(name)s " if self.show_name else "",
            " ",
            self.get_color(bg, fg, bold),
        format = "".join(template)
        who = [self.get_color("green"),
               getattr(record, "funcName", ""),
               self.get_color("black", None, True),
               str(getattr(record, "lineno", 0))]
        who = "".join(who)
        # We need to calculate padding length manualy
        # as color codes mess up string length based calcs
        unformatted_who = getattr(record, "funcName", "") + "()" + \
            ":" + str(getattr(record, "lineno", 0))
        if len(unformatted_who) < self.who_padding:
            spaces = " " * (self.who_padding - len(unformatted_who))
            spaces = ""
        record.padded_who = who + spaces
        formatter = logging.Formatter(format, self.date_format)
        self.colorize_traceback(formatter, record)
        output = formatter.format(record)
        # Clean cache so the color codes of traceback don't leak to other formatters
        record.ext_text = None
        return output
    def colorize_traceback(self, formatter, record):
        Turn traceback text to red.
        if record.exc_info:
            # Cache the traceback text to avoid converting it multiple times
            # (it's constant anyway)
            record.exc_text = "".join([
    def format(self, record):
        Formats a record for output.
        Takes a custom formatting path on a terminal.
        if self.is_tty:
            message = self.colorize(record)
            message = logging.StreamHandler.format(self, record)
        return message
if __name__ == "__main__":
    # Run test output on stdout
    import sys
    root_logger = logging.getLogger()
    handler = RainbowLoggingHandler(sys.stdout)
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
    logger = logging.getLogger("test")
    def test_func():
        logger.debug("debug msg")"info msg")
        logger.warn("warn msg")
    def test_func_2():
        logger.error("error msg")
        logger.critical("critical msg")
            raise RuntimeError("Opa!")
        except Exception as e:

 Subscribe to this blog in a reader Follow me on Twitter Follow me on Facebook Follow me Google+

March 13, 2013

Asko Soukka: Cross-browser test your Plone add-on with Robot Framework, Travis-CI and Sauce Labs

by Asko Soukka at 2013-03-13T16:56:44Z

Thanks to Rok Garbas, I became aware of Sauce Labsduring the Plone testing sprint.

Finally, I had some time to try it myself, and I managed to make it work pretty well with Robot Framework and Travis-CI.

I try to start from the very beginning, but if you already have Robot Framework tests, or even Travis-CI-integration, you could just skip these initial steps.

Bootstrap Templer

Create buildout directory for Templer installation:

$ mkdir templer-buildout
$ cd templer-buildout/


$ curl -o

Create buildout.cfg:

parts = templer

recipe = zc.recipe.egg
eggs =

Run bootstrap and buildout to install Templer:

$ python
$ bin/buildout

Create a new product with Templer

Call the buildout-installed to create a new product with Robot Framework test example:

$ templer-buildout/bin/templer plone_basic example.product

Be careful to answer true for the following question about including Robot test templates:

robot tests (should the default robot test be included) [false]: true

Run buildout:

$ cd example.product
$ python --distribute
$ bin/buildout

Update Robot Framework tests to be Selenium grid ready

Using Sauce Labs with Robot Framework (Selenium library) is similar to using robot with your own selenium grid. It mainly requires making the browser opening keyword configurable with a few selected variables.

Update src/example/product/tests/robot_test.txt with:

*** Settings ***

Library Selenium2Library timeout=10 implicit_wait=0.5

Suite Setup Start browser
Suite Teardown Close All Browsers

*** Variables ***

${ZOPE_HOST} = localhost
${ZOPE_PORT} = 55001
${ZOPE_URL} = http://${ZOPE_HOST}:${ZOPE_PORT}

${PLONE_SITE_ID} = plone

${BROWSER} = Firefox
${DESIRED_CAPABILITIES} = platform:Linux
${BUILD_NUMBER} = manual

*** Test Cases ***

Plone site
[Tags] start
Go to ${PLONE_URL}
Page should contain Plone site

*** Keywords ***

Start browser
${BUILD_INFO} = Set variable
... build:${BUILD_NUMBER},name:${SUITE_NAME} | ${TEST_NAME}
Open browser ${PLONE_URL} ${BROWSER}
... remote_url=${REMOTE_URL}
... desired_capabilities=${DESIRED_CAPABILITIES},${BUILD_INFO}

Let me explain those variables:

  • ZOPE_HOST should match the host for which ZServer is started during the test setup (ZServer host is configured with ZSERVER_HOST-environment variable. It defaults to localhost, but must be configured later to for testing Internet Explorer.

  • ZOPE_PORT should match the port number which ZServer is started to listen during the test setup (ZServer pot is configured with ZSERVER_PORT-environment variable. It defaults to 55001, which is just OK, until you wan to run multiple tests simultaneously on the same machine.

  • ZOPE_URL is a convenience variable for accessing Zope application root.

  • PLONE_SITE_ID is the Plone portal object id (and path name) for the test site. It default to plone, but it can be configured with PLONE_SITE_ID-environment variable. The default should be ok for most cases.

  • PLONE_URL is a convenience variable for accessing the Plone site front-page.

  • BROWSER selects the browser to run the tests with. The supported values depend on Selenium Python-package and can also be read from the documentation of Open browser-keyword in Selenium2Library keywords keyword documentation.

  • REMOTE_URL enables testing with Selenium grid by defining the url of the Selenium hub to use.

  • DESIRED_CAPABILITIES is used to pass various extra parameters for Selenium hub (e.g. the browser version to use or test metadata).

  • BUILD_NUMBER is used to identify the Travis-CI build on Sauce Labs.

When robot tests for Plone are run using bin/test, all the variables above can be overridden by defining corresponding ROBOT_-prefixed environment variable (e.g. ROBOT_REMOTE_URL).

Add Travis-CI configuration with Sauce Labs -support

There are a few steps in adding Travis-CI-support into your product.

At first, create travis.cfg to do the required magic for minimizing buildout-time and setting a few required environment variables. Thanks to the great community, we can just extend a public template:

extends =

package-name = example.product
package-extras = [test]

allow-hosts +=



environment = environment

Create .travis.yml for letting Travis-CI to know how the environment should be set up and the tests run:

language: python
python: '2.7'
- mkdir -p buildout-cache/eggs
- mkdir -p buildout-cache/downloads
- python -c travis.cfg
- bin/buildout -N -t 3 -c travis.cfg
- curl -O
- unzip
- java -jar Sauce-Connect.jar $SAUCE_USERNAME $SAUCE_ACCESS_KEY -i $TRAVIS_JOB_ID
- bash -c "while [ ! -f CONNECTED ]; do sleep 2; done"
script: bin/test
- kill $JAVA_PID

Let me describe:

  1. Lines 5–8: Run buildout.
  2. Lines 9–15: Download and start Sauce Connect.
  3. Line 16: Run tests.
  4. Lines 17–18: Shutdown Sauce Connect.
  5. Lines 19–22: Define required environment variables for letting robot to use Sauce Labs.
  6. Lines 23–26: Define build matrix for running the tests with Sauce Labs’ default Firefox, Chrome and Internet Explorer. tunnel-identifier-stuff is required for Sauce Labs to allow more than one simultaneous tunnels for the same user account.

Next, define your Sauce Labs username and access key as secret, encrypted, environment variables SAUCE_USERNAME and SAUCE_ACCESS_KEY.

Currently, Sauce Labs offers unlimited free subscription with three simultaneous connections (e.g. running tests for three different browsers at the same time) for Open Source projects. Just make sure to register the account for you project, not yourself. Public repository url is required for the account.

  1. Install Travis gem for Ruby (and install Ruby before that when required):

    $ gem install travis  # or sudo gem ...
  2. use travis-command to insert encrypted environment variables into the product’s .travis.yml:

    $ travis encrypt SAUCE_USERNAME=myusername -r mygithubname/example.product --add
    $ travis encrypt SAUCE_ACCESS_KEY=myaccesskey -r mygithubname/example.product --add

Make sure to use your own Sauce Labs username and access key, and your product’s Github-repository path (with format username/repo).

Finally, enable Travis-CI-tests for you product either at or at GitHub.

Done. If I forgot something, I’ll update this post.

Behind the basics: Test level status reporting for Sauce Labs

By default, Sauce Labs doesn’t really know did the Selenium tests on it pass or fail. To pass that information from our test runner on Travis-CI to Sauce Labs, we need to add some extra code into our test setup.

At first, append the following into the end of src/example/product/

# Inject keyword for getting the selenium session id
import Selenium2Library
_BrowserManagementKeywords.get_session_id = lambda self:\
except ImportError:

class Keywords(object):

def report_sauce_status(self, job_id, test_status, test_tags=[]):
import base64
import httplib
import os

import json
json # pyflakes
except ImportError:
import simplejson as json

username = os.environ.get('SAUCE_USERNAME')
access_key = os.environ.get('SAUCE_ACCESS_KEY')

if not job_id:
return u"No Sauce job id found. Skipping..."
elif not username or not access_key:
return u"No Sauce environment variables found. Skipping..."

token = base64.encodestring('%s:%s' % (username, access_key))[:-1]
body = json.dumps({'passed': test_status == 'PASS',
'tags': test_tags})

connection = httplib.HTTPConnection('')
connection.request('PUT', '/rest/v1/%s/jobs/%s' % (
username, job_id), body,
headers={'Authorization': 'Basic %s' % token}

return connection.getresponse().status

This code does two things:

  1. The first part monkey patches Selenium2Library with a custom keyword for providing access to test specific Selenium session id. This is the key (job id) for sending the test status back to Sauce Labs.

  2. The second part defines a custom Robot Framework keyword library with a keyword for passing the test status (and other information) back to Sauce Labs.

Next, we update src/example/product/tests/robot_test.txt to store the session id during the setup of every test and send the test result back to Sauce Labs during the teardown of every test (note how we had to replace suite setup and teardown with test setup and teardown):

*** Settings ***

Library Selenium2Library timeout=10 implicit_wait=0.5
Library example.product.testing.Keywords

Test Setup Start browser
Test Teardown Run keywords Report test status Close All Browsers

*** Variables ***

${ZOPE_HOST} = localhost
${ZOPE_PORT} = 55001
${ZOPE_URL} = http://${ZOPE_HOST}:${ZOPE_PORT}

${PLONE_SITE_ID} = plone

${BROWSER} = Firefox
${DESIRED_CAPABILITIES} = platform:Linux
${BUILD_NUMBER} = manual

*** Test Cases ***

Plone site
[Tags] start
Go to ${PLONE_URL}
Page should contain Plone site

*** Keywords ***

Start browser
${BUILD_INFO} = Set variable
... build:${BUILD_NUMBER},name:${SUITE_NAME} | ${TEST_NAME}
Open browser ${PLONE_URL} ${BROWSER}
... remote_url=${REMOTE_URL}
... desired_capabilities=${DESIRED_CAPABILITIES},${BUILD_INFO}
${SESSION_ID} = Get session id
Set test variable ${SESSION_ID} ${SESSION_ID}

Report test status
Report sauce status ${SESSION_ID} ${TEST_STATUS} ${TEST_TAGS}

This worked for me. I hope it works for you too.

example.product is available at:

Kees Hink: Robot Framework testing hints

by Kees Hink at 2013-03-13T13:25:09Z

Updates: 2013-03-13 Using Chrome driver in RF tests 2013-03-12 Notes about Plone-specificity Some things that come in handy when making Robot Framework test: Tags RF supports tags. Add a line [Tags] tag1 tag2: *** Test cases *** Scenario: Clicking the submit button hides it Given i am logged in and i am on an article When i simulate clicking the comment submit button Then the

March 12, 2013

Eau de Web Blog: Hello world!

by david at 2013-03-12T13:17:37Z

Welcome to WordPress. This is your first post. Edit or delete it, then start blogging!

March 11, 2013

Netsight Developers: Reading Roadshow May 2013

by Astra Baker at 2013-03-11T16:55:56Z

Due to the success of our Roadshow in Reading at the end of last year we have decided to do it again, in exactly the same location with exactly the same agenda.

Reading worked well for us and our delegates with the venue being conveniently located close to the train station - only two minutes across the road. So we thought why change what's not broken!

Our Roadshow events are aimed at anyone involved in the management or implementation of an Intranet. It is completely free to attend and includes a buffet lunch. As well as that our team of dedicated Developers & Project managers are on hand after the talks to discuss any questions you may have regarding potential upcoming Intranet projects or your existing internal communication systems.

We will also be giving away iPod shuffles to the first ten attendees to arrive on the day.

For more information:

Download our event overview PDF

Rok Garbas: final report!

by Rok Garbas at 2013-03-11T04:55:00Z

I actually released a week ago with good intention to record a screencast. But after of week of working on it I gave up and I'm announcing release without a screencast.

Before releasing it to public I gave my contributors a chance to help me test and and many bugs were fixed before releasing and some are assigned for next release. I can not stress how important this is for me - as a developer - to get feedback on my work, especially in shape of bug reports. Things can only get fixed if you report them.

Instead of listing what is working I'll list what is not working:

  • Search criteria widget in Collection content type is not yet working, but expect it to work in next release.
  • Related items widget is also not working, but work started on it already. Hopefully will also be part of next release.
  • Site Setup pages are not opening in overlay, since this is planned for later release.

At this point I would like to invite you to give a try and report back to issue tracker. Here is example buildout to get running locally with latest Plone release.:

extends =
versions = versions
parts = instance
recipe = plone.recipe.zope2instance
user = admin:admin
http-address = 7000
eggs =
zcml =
[versions] = 1.8.3 = 0.2 = 1.2

I already started with work for next release and I hope to release it after Plone Open Garden sprint which at the beginning of April (next month). In case you'll be also there and want to work on let me know.

Mikko Ohtamaa: Migrating and moving issues between Github issue trackers

by Mikko Ohtamaa at 2013-03-11T02:33:39Z

Some time ago I had to migrate issues from a Github project to another. In this particular case, I moved Plone CMS developer documentation issues from under my personal Github account to under the Plone’s collective community team project.


Github currently does not offer native support to move issues or issue trackers between projects. This is little strange, because I think it’s quite common use case that a personal project gets promoted under a team umbrella, the primary Github project gets changed and you want to move issues too.

Luckily, Github API provides some support for such manipulation. I found an old Python script by Max Korenkov for this very purpose. I refined the script to get it to a semi-working state to get my one off batch job done. Now, out of blue, Antoine Durieux apparently polished the script to make sure moving comments work.

So, meet, a crude hacked together piece of Python script shuffling your issues around. It also imports milestones and labels of Github project. The script uses raw urllib and Github v3 API for the heavy lifting.

If you know anything better for the task please let me know (in comments).

 Subscribe to this blog in a reader Follow me on Twitter Follow me on Facebook Follow me Google+

March 09, 2013

Josh Johnson: From Back Log To Ready For Work

by jjmojojjmojo at 2013-03-09T12:18:45Z


I’ve been thinking a lot about the backlog grooming and design process in Agile approaches like Scrum.

Something occurred to me recently: what I really want during this phase is true driving out of assumptions. I want to discuss and record implementation plans and discuss how we’re going to accomplish a given user story so that when we do estimation, it’s realistic.

A big part of that is the intermediate products, or project assets as I call them in the diagram – mockups, use cases, workflow (and other) diagrams, and prototypes. Proof of concept at various levels coupled with documenting the how of what we’ll do in the next sprint.

This diagram hopes to put this process, as I see it, into focus more directly than I think I could do through prose.

This is a mini-experiment of sorts – how much can I convey in a diagram without a lot of verbiage to accompany it?

As such, thoughts and comments are welcome.

David "Pigeonflight" Bain: Plone to the cloud in 3 easy steps

by David Bain at 2013-03-09T04:14:25Z

update: the admin password is now autogenerated, I've made a note of how you can retrieve it. Before you start You will need: 5 to 10 minutes of spare time. a  reliable internet connection  a Cloud9 IDE account  a Dotcloud account  Have your login information for both Cloud9 IDE and Dotcloud close at hand. Disclaimer: The underlying tools for managing Plone on Dotcloud from Cloud9 IDE

March 08, 2013

Niteoweb: Load overrides.zcml in

by Nejc Zupan at 2013-03-08T19:13:10Z

Today I was working on a project where we use overrides.zcml to easily override some default Plone behavior. All was working fine (in the browser, that is) until I started writing tests for our custom behavior.

First thing I noticed was that the overrides.zcml was not loaded in our test layer. "Doh, I need to load it manually with the loadZCML() method!" I thought to myself. Boy was I wrong :).

The problem with using loadZCML() is that it loads whatever ZCML you tell it to load in a "normal" way. So, obviously, you get conflict errors, since declarations in your overrides.zcml directly map declarations that they override. Hence I needed to find a way to tell to load my overrides.zcml in an "override" manner and not throw conflict errors.

After quite some research and asking around, I got a tip from JC Brand on the #plone IRC channel: use xmlconfig.includeOverrides(). This indeed got me the exact result I wanted.

Here's a snippet for my future self and any other plonista struggling with the same problem that happen to stumble upon this blog:

from import PLONE_FIXTURE
from import PloneSandboxLayer
from plone.testing import z2
from zope.configuration import xmlconfig
class MyProductLayer(PloneSandboxLayer):
    defaultBases = (PLONE_FIXTURE,)
    def setUpZope(self, app, configurationContext):
        import my.product
        xmlconfig.includeOverrides(configurationContext, 'overrides.zcml', package=my.product)
        z2.installProduct(app, 'my.product')

March 07, 2013

Domen Kožar: Contributions in February

by Domen Kožar at 2013-03-07T23:30:00Z

Following is a monthly update on my contributions to open source and community around it.

If you have an interesting problem to solve under a public license, I'm happy to hear from you at :-)

Cheers, Domen

Netsight Developers: What can Software Learn from A Dresden Doll?

by Matt Hamilton at 2013-03-07T23:22:38Z

A few days ago, I saw a tweet from Simon Phipps pointing out a TED talk done last month by Amanda Palmer. In his blog post Simon highlighted the final words of Amanda in her talk on the music industry:

People have been obsessed with the wrong question: "How do we /make/ people pay for music?" What if we start asking "How do we /let/ people pay for music?".


I love Amanda Palmer, I think her music is fantastic, and I love the energy and off-the-wall-ness of it. Watching her hobble around the streets of [blah] with her band playing the Ukelele and singing in a phone-box is awesome. She was once playing a gig with her band The Dresden Dolls in Oakland, whilst I was just down the road in San Francisco and I didn't realise until it was over… which was gutting.

Amanda has done a number of experiments with regards to economic models for her music. In short, she talks about *trust*. Rather than try to demand people pay for your art, trust them to pay you for it instead.

I'm currently on my way to the massive CeBIT expo in Hannover to man the Plone stand at the CMS Gardens area. This is a sub-expo of Open Source Content Management systems all in one place. There will b a number of individuals from the Plone community coming together to promote Plone at the event.

What has Amanda Palmer's talk on the music industry got to do with Open Source software?

One of things Amanda talks about is letting her fans and community support her. She decided to give her music away freely and to encourage copying and distribution of her music. She was amazed to see what a response she got and how many people backed her ventures.

Sound familiar? Yes, it sounds a bit like Open Source software. Open Source software in it's purest community-driven sense. Not the openwash-type thing where a company decides to release an 'open source' version of their product as a loss leader.

Even within Open Source Software things have been changing. New tools and new ways of connecting with people have been a catalyst for new ways to connecting with developers and customers. Github, the social coding platform has enabled the lowest bar of entry we have ever seen.

Going beyond that Gittip, the service that allows you to /tip/ developers small sums of cash for the work they are doing. Someone fixes a bug in your code? Maybe tip them. Some developers have been moving to this model as an experiment in working full time. Rather than be a part of one particular company or contract to one particular client, they are using tools like Gittip and Chipin to crowd sourcing the funding of developing features for software directly. Within the Plone community we have people like Rok Garbas, Lennart Regebro, Nejc Zupan, Nathan Van Gheem and others who have come forward at points to ask for people to directly support the development work they are doing.

As Amanda says in her talk: "It's kinda counterintuitive for a lot of artists, they don't want to ask for things. It is not easy. It is not easy to ask. A lot of artists have a problem with this. Asking makes you vulnerable". I think many of the developers I've mentioned could be considered artists. Artists in the code they produce and the work they do. Many people do not appreciate the creativity involved in software development. Taking this further, a peer of mine when I was studying Computer Science at the University of Bristol, Chris Parsons went on to be a part of a whole movement called 'Software Craftmanship'.

All of this takes trust. WIthout trust none of this works. You have to be able to trust that the work will be done, and you have to trust that there are people there to pay for it.

Amanda talks of stage diving, and stripping naked and being drawn on by fans. Now, I'm not suggesting developers go that far ;) That said… in the early days of the Plone community there was an annual event in the Austrian Alps called the Snow Sprint. 30-odd developers locked away in a log cabin at the top of a mountain coding away, drinking beer and sitting in the sauna. I think once you've sat naked in a Sauna with someone and dived out to roll in the snow to cool off… you can probably trust them with code.

But it does highlight the importance of connecting with people and building those connections.

That is why I'm sat on a plane right now, heading to an Expo to meet up with a number of Plone developers whom I must see three or four times a year somewhere in the world. Building those connections, and trust. Not just within our community, but also to meet new people and to talk to them about Plone and to extend that trust further.

Amanda talked about people being confused by 'no hard sticker price'. The concept of you paying what you think something is worth to you. People see it as a risk. In her mind it is not a risk, but an expression of trust.

But music is a very personal thing. How does that translate into the enterprise? Can we make the same leaps that Amanda Palmer is making in the music world in our world of software?

Kees Hink: My Barcelona Testing Sprint

by Kees Hink at 2013-03-07T14:19:32Z

[edit 14-2: see bottom of article for information that came after the sprint] The Barcelona Sprint was about Plone's testing. Most of Plone's code is covered by tests, and these tests are automatically run by a Jenkins server, so we know when stuff starts not working anymore. One focus of the sprint was improving the Jenkins setup, so a commit or pull request that breaks the build