[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