[GRASS-dev] replace G_debug C function with a python one only for the Module class (pygrass)

Dear all,

I would like to remove the line 680:

{{{
get_msgr().debug(1, self.get_bash())
}}}

from the run method of the Module class.

I would like to remove it because the get_msgr is using ctypes (grass.lib.gis),
this it means that all the LD_LIBRARY_PATH must be set correctly.

Set the LD_LIBRARY_PATH could be a problem, for example if you try to use
the class from QGIS, because it require to launch QGIS with something like;

{{{
#!/usr/bin/sh
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$GISBASE/lib \
PATH=$PATH:$GISBASE/bin:$GISBASE/scripts:$HOME/.grass7/addons/bin:$HOME/.grass7/addons/scripts
\
PYTHONPATH=$PYTHONPATH:$GISBASE/etc/python:$GISBASE/gui/wxpython \
GRASS_ADDON_BASE=$HOME/.grass7/addons qgis
}}}

On the other hand, I understand that we need the debug. therefore I
was thinking to provide the same functionalities but avoiding to call
directly the G_debug functions, G_debug is define as follow:

{{{
int G_debug(int level, const char *msg, ...)
{
    char *filen;
    va_list ap;
    FILE *fd;

    G_init_debug();

    if (grass_debug_level >= level) {
va_start(ap, msg);

filen = getenv("GRASS_DEBUG_FILE");
if (filen != NULL) {
   fd = fopen(filen, "a");
   if (!fd) {
G_warning(_("Cannot open debug file '%s'"), filen);
return 0;
   }
}
else {
   fd = stderr;
}

fprintf(fd, "D%d/%d: ", level, grass_debug_level);
vfprintf(fd, msg, ap);
fprintf(fd, "\n");
fflush(fd);

if (filen != NULL)
   fclose(fd);

va_end(ap);
    }

    return 1;
}
}}}

and I'm defining a function (probably is still too simple) such as:

{{{
from __future__ import print_function
import os
import sys

def get_env():
    gisrc = os.environ.get('GISRC')
    if gisrc is None:
        raise RunError('You are not in a GRASS session')
    with open(gisrc, mode='r') as grc:
        env = {k.strip(): v.strip() for k, v in [row.split(':') for
row in grc if row]}
    return env

def get_debug_level():
    debug = get_env().get('DEBUG')
    return int(debug) if debug else 0

def G_debug(level, *msg):
    debug_level = get_debug_level()
    if debug_level >= level:
        dfile = os.environ.get("GRASS_DEBUG_FILE")
        fd = sys.stderr if dfile is None else open(dfile, mode='a')
        print("D%d/%d: " % (level, debug_level), *msg, end='\n', file=fd)
}}}

Concerning the performance of course the python version is slower but
only 6 times:

{{{
%timeit G_debug_python(5, 'provami...')
The slowest run took 9.75 times longer than the fastest. This could
mean that an intermediate result is being cached
100000 loops, best of 3: 13.8 µs per loop

In [25]: %timeit G_debug_grass(5, 'provami...')
The slowest run took 32.00 times longer than the fastest. This could
mean that an intermediate result is being cached
100000 loops, best of 3: 2.35 µs per loop
}}}

But in this way the ctypes are not required by the pygrass.modules
classes and functions.

What do you think?
Other ideas and/or solutions?

Best regards

Pietro