Wollen wir weitere Entwicklungswerkzeuge in einem Buildout-Projekt installieren, geben wir diese einfach in der buildout.cfg-Datei an. Folgende Entwicklungswerkzeuge können die Arbeit deutlich vereinfachen:
- DocFinderTab
Produkt, das alle Klassen und Methoden eines Objekts im Zope Management Interface (ZMI) auflistet.
DocFinderTab kann direkt als Egg in der Instanz angegeben werden:
[instance] … eggs = Products.DocFinderTab
- pyflakes
Pyflakes analysiert Python-Programme und entdeckt verschiedene Fehlerarten. Es ist sehr viel schneller als das Ausführen der Programme.
pyflakes lässt sich einfach mit Buildout installieren:
parts = … pyflakes [pyflakes] recipe = zc.recipe.egg:scripts eggs = pyflakes scripts = pyflakes entry-points = pyflakes=pyflakes.scripts.pyflakes:main
- plone.app.debugtoolbar
Debug-Toolbar, die einfach für eine Plone-Site aktiviert werden kann. Die Installation kann einfach mit Buildout erfolgen:
[instance] … eggs = plone.app.debugtoolbar
- pylint
Pylint analysiert Python-Code in Bezug auf Bugs und geringe Code-Qualität.
Pylint lässt sich einfach mit Buildout installieren:
parts = pylint … [pylint] recipe = zc.recipe.egg eggs = ${instance:eggs} pylint entry-points = pylint=pylint.lint:Run arguments = sys.argv[1:]
- DeadlockDebugger
- Für entsprechende Prozesse wird Debugging möglich, indem ein Traceback aller laufenden Pythonprozesse sowohl zum Eventlog als auch zum Browser geschickt wird.
- PDBDebugMode
PDBDebugMode erlaubt sog. post-mortem-Debugging für exceptions im Debug-Modus, d.h., bei einem Fehler wird der Debugger aufgerufen, der den Traceback ausgibt. Sofern vorhanden, nutzt PDBDebugMode ipdb statt pdb.
Diese Entwicklungswerkzeuge lassen sich einfach angeben mit:
[instance] … debug-mode = on eggs = Products.PDBDebugMode z3c.deadlockdebugger
- Products.PrintingMailHost
- Monkey Patch, der MailHost-Nachrichten nicht verschickt, sondern auf der Konsole ausgibt, d.h., Zope versendet damit keine Mails mehr.
- roadrunner
Testrunner, der die testgetriebene Entwicklung deutlich beschleunigen kann.
roadrunner läd vorab das Standard-Zope- und Plone-Environment für PloneTestCase. zur Installation wird einfach folgendes in die buildout.cfg-Datei eingetragen:
[buildout] parts = … roadrunner [roadrunner] recipe = roadrunner:plone packages-under-test = vs.policy
Anschließend kann es wie der reguläre Zope-Testrunner aufgerufen werden:
$ ./bin/roadrunner -s vs.policy
- collective.recipe.grp
Rezept, mit dem in Buildout auf ${grp:GROUP} referenziert werden kann um die Gruppe des aktuellen Nutzers herauszubekommen.
Zusammen mit gocept.recipe.env, das Environment-Variablen in einem Buildout-Abschnitt zur Verfügung stellt, lassen sich hiermit die Eigentümer (Owner) der Buildout-Inhalte setzen lassen, z.B. mit:
chown -R ${env:USER}:${grp:GROUP} ${buildout:directory}
Installieren lassen sich die Pakete mit:
[env] recipe = gocept.recipe.env [grp] recipe = collective.recipe.grp
- IPython
Python-Shell, die Ihnen u.a. folgende Vorteile bietet:
- Objekt-Introspektion
- Code- Introspektion
- Dokumentation-Introspektion (mit %pdoc)
- Eingabehistorie, persistent auch über Sessions hinweg.
Zur Installation fügen Sie bitte folgendes in Ihrer devel.cfg-Datei hinzu:
[buildout] _ parts = _ ipzope _ [ipzope] # An IPython Shell for interactive use with Zope running. # # It requires the `ipy_profile_zope.py` configuration script. Get this from # git@github.com:collective/dotipython.git and put it in your profile # directory. Depending on your setup, this may be at # `$HOME/.ipython/profile_zope/startup`, # `$HOME/.config/ipython/profile_zope/startup` (Ubuntu 12.04), or see # http://ipython.org/ipython-doc/dev/config/overview.html#configuration-file-location # for more details. # recipe = zc.recipe.egg eggs = ipython ${instance} initialization = import sys, os os.environ["INSTANCE_HOME"] = "${instance:location}" sys.argv[1:1] = "--profile=zope".split() scripts = ipython=ipzope
Rufen Sie dann zunächst das buildout-Skript auf. Anschließend können Sie dann die IPython-Sell aufrufen:
$ ./bin/buildout $ ./bin/ipzope
Beim ersten Aufruf von ipzope wird ein neues IPython-Profil in Ihrem Home-Verzeichnis erstellt. In *ix-Betriebssystemen finden Sie das entsprechende Verzeichnis unter $HOME/.ipython/, in Windows unter %userprofile%\_ipython. In dieses Verzeichnis sollten das Profil aus https://github.com/collective/dotipython/blob/master/ipy_profile_zope.py legen. Anschließend sollten Sie die IPython-Session mit Ctrl-d beenden und erneut starten.
Anschließend lässt sich z.B. portal.error_log.get eingeben und durch Drücken der Tab-Taste erhalten Sie alle verfügbaren Methoden des èrror_log`, die mit get beginnen.
Falls Sie Änderungen an Ihrer Plone-Site vorgenommen haben, können Sie diese speichern mit:
utils.commit()
Und falls auch andere auf der Zope-Instanz arbeiten, sollten Sie gelegentlich die Änderungen übernehmen mit:
utils.sync()
Weitere Informationen zu iPython erhalten Sie im iPython-Tutorial.
- ipdb, iw.debug
ipdb ist Python-Debugger, der viele Vorteile von IPython nutzt, z.B. automatische Vervollständigung. iw.debug erlaubt Ihnen, den ipdb- Debugger über jedem veröffentlichten Objekt einer Zope2-Anwendung aufzurufen.
Zum Installieren fügen Sie in Ihrer devel.cfg-Datei folgendes hinzu:
[buildout] _ [instance] eggs += _ iw.debug _ [instance] _ zcml += iw.debug
Anschließend wird das Buildout-Skript aufgerufen und die Instanz im Vordergrund gestartet:
$ ./bin/buildout $ ./bin/instance fg
Anmerkung: Wenn in Ihrem Code an irgendeiner Stelle ein ipdb oder pdb Code enthalten ist, erhalten Sie die Exception BdbQuit.
Nun kann der URL eines jeden Objekts der Plone-Site /ipdb angehängt werden um eine IPython-Shell für diese Plone-Site zu erhalten:
… --Return-- None > /Users/veit/.buildout/eggs/iw.debug-0.3-py2.7.egg/iw/debug/pdbview.py(92)pdb() 91 else: ---> 92 set_trace() 93
Um die lokalen Variablen zu erhalten, können Sie nun zunächst ll eingeben:
ipdb> ll {'request': <HTTPRequest, URL=http://localhost:8080/Plone/ipdb>, 'portal': <PloneSite at /Plone>, 'context': <PloneSite at /Plone>, 'meth': None, 'view': None} ipdb> context <PloneSite at /Plone> ipdb> context == portal True ipdb> portal.Title() 'Website' ipdb> portal.portal_quickinstaller.listInstallableProducts() [{'status': 'new', 'hasError': False, 'id': 'plone.app.dexterity', 'title': u'Dexterity Content Types'}, {'status': 'new', 'hasError': False, 'id': 'plone.app.theming', 'title': u'Diazo theme support'}, {'status': 'new', 'hasError': False, 'id': 'plone.app.caching', 'title': u'HTTP caching support'}, {'status': 'new', 'hasError': False, 'id': 'Marshall', 'title': 'Marshall'}, {'status': 'new', 'hasError': False, 'id': 'plone.app.openid', 'title': u'OpenID Authentication Support'}, {'status': 'new', 'hasError': False, 'id': 'plone.app.debugtoolbar', 'title': u'Plone debug toolbar'}, {'status': 'new', 'hasError': False, 'id': 'plone.session', 'title': u'Session refresh support'}, {'status': 'new', 'hasError': False, 'id': 'plone.resource', 'title': u'Static resource storage'}, {'status': 'new', 'hasError': False, 'id': 'CMFPlacefulWorkflow', 'title': u'Workflow Policy Support (CMFPlacefulWorkflow)'}, {'status': 'new', 'hasError': False, 'id': 'plone.app.iterate', 'title': u'Working Copy Support (Iterate)'}, {'status': 'new', 'hasError': False, 'id': 'collective.z3cform.datetimewidget', 'title': u'collective.z3cform.datetimewidget'}] ipdb>