Most Powerful Open Source ERP

How To Debug ERP5

How To showing tips and tricks on debugging ERP5.
  • Last Update:2016-04-27
  • Version:001
  • Language:en

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