This howTo includes tips and tricks on debugging ERP5 (and is in dire need of an update!)
Table of Contents
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:
def bind(*args, **kw):
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:
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:
from Testing.makerequest import makerequest
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:
user = app.erp5.acl_users.getUserById('username')
user = user.__of__(app.erp5.acl_users)
from AccessControl.SecurityManagement import newSecurityManager
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¶
get_transaction().commit()
While using zopectl debug you'll observe that activities aren't invoked - you
can invoke them using this:
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:
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) :
(Pdb) open('/tmp/x.py', 'w').write(context.Python_script.document_src())
Edit the file /tmp/x.py and edit the Python script:
(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:
(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:
(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:
# portal is fetched already
>>> portal.erp5_sql_connection.connection_string = 'new connection string'
>>> portal.erp5_sql_deferred_connection.connection_string = 'new connection string'
>>> portal.erp5_sql_transactionless_connection.connection_string = 'new connection string'
>>> get_transaction().commit()
>>> ^D
Now after starting Zope ERP5 will use new connection string.
Note: /!\ 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¶
Related Articles¶