[Zope] how to programmatically control zope?

bruno modulix bruno at modulix.org
Fri Sep 16 05:00:45 EDT 2005


akonsu wrote:
> hello, would someone please point me to the right direction? what is
> the preferred way to control a zope server programmatically? i need to
> be able to administer my zope instance from a script. add users,
> change permissions, create new sites, add objects to the sites. there
> is webdav, xml-rpc, what else? 

Interactively control/inspect/play with the server:
<ZOPE_INSTANCE>/bin/zopectl debug

Run a script on the server:
<ZOPE_INSTANCE>/bin/zopectl run <myscript.py> [args...]

There are a few tricks however:

1/ You can't run zopectl debug or zopectl run while you instance is
running (as it locks the ZODB). The solution here is to set up a zeo
instance (this is really easy), and have 2 zope instances, one serving
the web requests, the other being used for debug/run

2/ changes made from the debug interactive shell or a script needs to be
explicitely commited. The idiom is:

# ... your code here
get_transaction.commit()
app._p_jar.sync() # app is the root zope object

3/ When accessing your zope server this way, you have the default
Anonymous role. If you need Admin privileges (which may well be the case
!-), you have to 'log in' by code. Here's a snippet I stoled from
I-Can't-Remember-Where-But-Thanks-Anyway(tm) :

from AccessControl.SecurityManagement import newSecurityManager

def login(app, username):
  acl = app.acl_users
  user = acl.getUserById(username)
  assert user is not None
  user = user.__of__(acl)
  newSecurityManager(None, user)

login(app, "myadminlogin")

4/ Some Products or methods may need a REQUEST object, which is not
provided by default. Here's a way to simulate one:

from os import environ
from sys import stdin, stdout
from ZPublisher.HTTPRequest import HTTPRequest
from ZPublisher.HTTPResponse import HTTPResponse
from ZPublisher.BaseRequest import RequestContainer
from ZPublisher import Publish
from thread import get_ident

def makerequest(app, stdout=stdout):
  # copy/hacked from Testing.makerequest
  resp = HTTPResponse(stdout=stdout)
  environ['SERVER_NAME']='foo'
  environ['SERVER_PORT']='80'
  environ['REQUEST_METHOD'] = 'GET'
  req = HTTPRequest(stdin, environ, resp)

  # first put the needed values in the request
  req['HTTP_ACCEPT_CHARSET'] = 'latin-15'
  req['HTTP_ACCEPT_LANGUAGE'] = 'fr'
  # etc, just fill what you need in the request	

  # then store the request in Publish._requests
  # with the thread id
  id = get_ident()
  Publish._requests[id] = req

  # ok, let's wrap and return
  return app.__of__(RequestContainer(REQUEST = req))

app = makerequest(app)


Most - if not everything - of what you do via the ZMI can be done by
code. Reading the ZMI and the base Products source code may be a good
way to learn the API.

> which one is the right way to do it?

Depends on your needs.

> i am a newbie i hope this is not a frequent question, at least i did
> not find an answer in the documentation...

This is usually not what newbies starts with !-)

And I'm afraid that Zope's documentation is not always that helpful to
newbies - not that it's that bad, but documentation, being freely
contributed, is not always the strongest point of OSS projects, and Zope
is quite a complex application anyway, so it's not easy to document.
There again, it's mostly "Use The Code, Luke".

HTH
-- 
Bruno Desthuilliers
Développeur
bruno at modulix.org


More information about the Zope mailing list