Monthly Archives: July 2013

Write a Plone CLI maintenance script

This is a quick tip on how to write your own command line maintenance scripts for your Plone application.

Recently one of our clients expressed a need for a maintenance script which would walk the database of a Plone application and, for every object, print out all the roles users have assigned on that object. Since we were dealing with a large database, processing it would take a considerable amount of time, rendering a solution with a browser view (or similar) not particularly useful. We needed some kind of a command line utility which would occasionally be run in the background (e.g. as a cron job) and would output results to a file.

The question which arised next was how to write such a Python script so that it would hook up to the Plone application, its database and would at the same time already have access to all the Plone utilities it might need (i.e. Products.CMFCore). I searched around the internet quite a bit before I finally stumbled upon the missing part.

It turned out to be pretty easy actually. The key is to define a zopectl.command entry point in your package’s setup.py (i.e. in a package containing your maintenance script):

setup(
    ...

    entry_points="""
    [zopectl.command]
    dump_roles = your.package.module:some_callable
    """,

    ...
)

You can then add this package as a dependency of the bigger Plone project, run the buildout and there it is – your maintenance script (named dump_roles in our example) can be called like this:

$ bin/instance dump_roles <arguments>

When you run the command, some_callable from the your.package.module (as defined in setup.py) will be invoked. The callable will receive two arguments – the Zope root application object (as a starting point of object traversal) and the additional command-line arguments that might have been used on script invocation.

For the sake of completeness, here’s a skeleton of the actual maintenance script (defined in your.package.module):

def some_callable(app, cmd_args):
    """Module's entry point (zopectl.command).

    :param app: Zope root application object
    :param cmd_args: list of command line arguments used to invoke the command
    """
    pass  # your maintenance code goes here ...

Happy coding!