Contents
Introduction and preparation
psyco issue
ERP5 uses psyco when available (usually on all 32bits machines), but psyco disable pdb, so if you want to use pdb, you'll have to disable psyco manually. If you have a recent ERP5Type product, you can modify Products/ERP5Type/PsycoWrapper.py to use the dummy psyco module (you should understand by looking at this code).
If you use older version, you have to create a dummy psyco.py in your PYTHONPATH, containing, for example:
1 def bind(*args, **kw):
2 pass
Make sure this psyco module will be the first in your python path, for example by putting it in $INSTANCE_HOME/lib/python/psyco.py
Below shell code will automagically create needed file:
mkdir -p $INSTANCE_HOME/lib/python echo -e "def bind(*args, **kawrgs):\n pass" > $INSTANCE_HOME/lib/python/psyco.py
Debugging
Simple solution - using pdb
The simplest solution is to use:
1 import pdb; pdb.set_trace()
Somewhere in python code. To have console attached start zope in foreground mode:
zopectl fg
debugging Python Scripts
For python scripts, you are not allowed to use pdb directly. One solution is create one external method with the previous code. Other solution is use zdb. zdb is a Zope Product that allows use set_trace inside PythonScripts directly at ZMI.
from Products.zdb import set_trace; set_trace()
To have console attached start zope in foreground mode:
zopectl fg
Using zopectl debug facility
You might know already, that it is possible to debug zope using zopectl debug facility. There are some ERP5-specific issues related.
After invoking zopectl debug you need to wrap site with a REQUEST using:
1 from Testing.makerequest import makerequest
2 portal = makerequest(app.erp5)
Where erp5 is name of your site.
You might also like to have some privileges while debugging, to achieve it use following code:
1 user = app.erp5.acl_users.getUserById('username')
2 user = user.__of__(app.erp5.acl_users)
3 from AccessControl.SecurityManagement import newSecurityManager
4 newSecurityManager(None, user)
Substitute app.erp5.acl_users with your user folder and username with username to which you'd like to login.
PDBDebugMode
If you want to use PDBDebugMode, and are using iHotfix, you have to apply this patch to Products/iHotfix:
diff -u iHotfix.orig/__init__.py iHotfix/__init__.py
--- iHotfix.orig/__init__.py 2008-09-23 12:06:02.707936781 -0400
+++ iHotfix/__init__.py 2008-09-23 12:06:34.418025744 -0400
@@ -72,7 +72,7 @@
_the_lock = allocate_lock()
-def new_publish(zope_request, module_name, after_list, debug=0):
+def new_publish(zope_request, module_name, after_list, debug=0, **kw):
# Build the Context instance, a wrapper around the Zope request
context = Context(zope_request)
# Store it
@@ -85,7 +85,7 @@
try:
# Publish
- x = Publish.zope_publish(zope_request, module_name, after_list, debug)
+ x = Publish.zope_publish(zope_request, module_name, after_list, debug, **kw)
finally:
# Remove the context object.
# When conflicts occur the "publish" method is called again,
Important issues
Committing changes into ZODB
To commit changes into ZODB use:
1 get_transaction().commit()
While using zopectl debug you'll observe that activities aren't invoked - you can invoke them using this:
1 portal.portal_activities.process_timer(0, 0)
Fetching changes from ZODB/Zope
To synchronise your debug session with current Zope state you need to use such snippet:
1 portal._p_jar.sync()
Edit python scripts while debugging with pdb
To change the content of a python script ('Python_script' in the above example) :
1 (Pdb) open('/tmp/x.py', 'w').write(context.Python_script.document_src())
Edit the file /tmp/x.py and edit the Python script:
1 (Pdb) context.Python_script.write(open('/tmp/x.py').read())
You can add this to your .pdbrc :
alias edit import os; open('/tmp/x.py', 'w').write(%1.document_src()); os.system('%s /tmp/x.py' % os.environ.get('EDITOR', 'vim')); %1.write(open('/tmp/x.py').read())and then use the macro like that:
1 (Pdb) edit context.Python_script
Getting the current user name while debugging with pdb
You can add this to your .pdbrc :
alias whoami from AccessControl import getSecurityManager; getSecurityManager().getUser()
and then use the macro like that:
1 (Pdb) whoami
Changing SQL connections with offline Zope
It is quite common practice to copy problematic Data.fs file to test machine. But SQL connection strings are hardcoded, so it is possible, that after running this Data.fs it will connect to original database - that would be disaster - or, it won't be possible to run this Data.fs as MySQL database won't be available.
There is solution. Run zopectl debug, use above snippets to fetch portal, then edit erp5_sql_connection, erp5_sql_deferred_connection and erp5_sql_transactionless_connection. Example:
1 # portal is fetched already
2 >>> portal.erp5_sql_connection.connection_string = 'new connection string'
3 >>> portal.erp5_sql_deferred_connection.connection_string = 'new connection string'
4 >>> portal.erp5_sql_transactionless_connection.connection_string = 'new connection string'
5 >>> get_transaction().commit()
6 >>> ^D
Now after starting Zope ERP5 will use new connection string.
Same might apply to configuring portal activities' load balancing system offline.
Scripting changes
To script above change you might use pipes, eg:
bash$ echo -e "portal.erp5_sql_connection.connection_string = 'new connection string'\nportal.erp5_sql_deferred_connection.connection_string = 'new connection string'\nportal.erp5_sql_transactionless_connection.connection_string = 'new connection'\nget_transaction().commit()\n" | zopectl debug
External references
How-To Debug, the debugging process - http://www.airs.com/ian/essays/debug/debug.html
Debug a spinning Zope - http://www.zope.org/Members/4am/debugspinningzope
Zope Script Debugging - http://www.zope.org/Members/regebro/ScriptDebugging
Debugging page on ZopeWiki - http://zopewiki.org/Debugging
Zope Wiki Pdb Debugging information - http://wiki.zope.org/zope2/DebuggingWithPdb