Changeset 523

Show
Ignore:
Timestamp:
04/19/05 16:45:54 (4 years ago)
Author:
abauer
Message:

svn merge -r 494:519 ../../branches/python-swig/

Merged the changes from the python plugin that is based
on swig

Location:
plugins/python-module
Files:
4 removed
4 modified
1 copied

Legend:

Unmodified
Added
Removed
  • plugins/python-module

    • Property svn:ignore
      •  

        old new  
        2121stamp-h1 
        2222libtool 
         23.project 
         24.cdtproject 
  • plugins/python-module/Makefile.am

    r487 r523  
    22pythonplgdir=@OPENSYNC_PYTHONPLG_DIR@ 
    33 
     4INCLUDES = -I$(top_srcdir) 
     5 
    46OPENSYNC_LIBS=-lopensync 
    5  
    6 #FIXME: set EXTRA_DIST 
    7  
    8 EXTRA_DIST = \ 
    9         src/pywrap.c \ 
    10         src/opensync.pyx 
    117 
    128plugin_LTLIBRARIES = python_module.la 
     
    1511python_module_la_LDFLAGS = @PYTHON_LDFLAGS@ -avoid-version -export-dynamic -module $(OSYNC_LIBS) 
    1612python_module_la_CFLAGS = -Wall -Werror $(OSYNC_CFLAGS) 
    17 python_module_la_CPPFLAGS = @PYTHON_CFLAGS@ \ 
    18         -DOPENSYNC_PYTHONPLG_DIR=\"$(pythonplgdir)\" 
     13python_module_la_CPPFLAGS = @PYTHON_CFLAGS@ -DOPENSYNC_PYTHONPLG_DIR=\"$(pythonplgdir)\" 
    1914python_module_la_LIBADD = @PYTHON_LIBS@ 
    2015 
    21  
    22  
    23 src/opensync.c: src/opensync.pyx 
    24         pyrexc $< 
    25  
    26 # opensync python module building rules 
    27 # It uses setup.py and distutils to 
    28 # make things easier 
    29 opensync.so: src/opensync.c setup.py 
    30         CFLAGS="$$CFLAGS $(OSYNC_CFLAGS)" python setup.py build_ext 
    31  
    32 all-local: opensync.so 
    33  
    34 install-exec-local: 
    35         python setup.py install 
    36  
    37 clean-local: 
    38         python setup.py clean 
     16pythonplg_DATA = src/sample 
  • plugins/python-module/configure.in

    r487 r523  
    6767                os_cv_python_sdk=yes])])]) 
    6868 
    69 PKG_CHECK_MODULES(OSYNC, [opensync-1.0]) 
     69export PKG_CONFIG_PATH=$prefix/lib/pkgconfig:${PKG_CONFIG_PATH} 
     70PKG_CHECK_MODULES(OSYNC, [opensync-1.0 glib-2.0]) 
    7071 
    7172OPENSYNC_CONFIGDIR=$(pkg-config --variable=configdir opensync-1.0) 
  • plugins/python-module/src/python_module.c

    r489 r523  
    1010#include <opensync/opensync.h> 
    1111#include <signal.h> 
    12  
    13 #include "pywrap.h" 
    14  
    15 struct MemberData { 
     12#include <glib.h> 
     13#include "config.h" 
     14 
     15typedef struct MemberData { 
    1616        PyThreadState *interp_thread; 
    1717        PyObject *module; 
    1818        PyObject *object; 
    19         PyObject *osync_module; 
    20 }; 
    21  
    22 /** Insert plugin search path in sys.path 
    23  * 
    24  * Isn't there an easier way of setting it? 
    25  * 
    26  *FIXME: It would be better if we just load modules from 
    27  * their filename, not setting the module search path 
    28  */ 
    29 static int change_sys_path() 
    30 { 
    31         int rv = -1; 
    32         PyObject *sys = NULL; 
    33         PyObject *path = NULL; 
    34         PyObject *dir = NULL; 
    35  
    36         sys = PyImport_ImportModule("sys"); 
    37         if (!sys) goto error; 
    38  
    39         path = PyObject_GetAttrString(sys, "path"); 
    40         if (!path) goto error; 
    41  
    42         dir = PyString_FromString(OPENSYNC_PYTHONPLG_DIR); 
    43         if (!dir) goto error; 
    44  
    45         if (PyList_Insert(path, 0, dir) < 0) 
    46                 goto error; 
    47  
    48         /* Success */ 
    49         rv = 0; 
    50  
    51 error: 
    52         Py_XDECREF(dir); 
    53         Py_XDECREF(path); 
    54         Py_XDECREF(sys); 
    55         return rv; 
     19} MemberData; 
     20 
     21static PyObject *pm_load_opensync(OSyncError **error) 
     22{ 
     23        PyObject *osync_module = PyImport_ImportModule("opensync"); 
     24        if (!osync_module) { 
     25                osync_error_set(error, OSYNC_ERROR_GENERIC, "Couldn't load OpenSync module"); 
     26                PyErr_Print(); 
     27                return NULL; 
     28        } 
     29        return osync_module; 
     30} 
     31 
     32static PyObject *pm_load_script(const char *filename, OSyncError **error) 
     33{ 
     34        FILE *fp = fopen(filename, "r"); 
     35        if (!fp) { 
     36                osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to open file %s", filename); 
     37                return NULL; 
     38        } 
     39         
     40        if (PyRun_SimpleFile(fp, filename) == -1) { 
     41                osync_error_set(error, OSYNC_ERROR_GENERIC, "Couldn't run module from file %s", filename); 
     42                PyErr_Print(); 
     43                return NULL; 
     44        } 
     45         
     46        PyObject *module = PyImport_AddModule("__main__"); 
     47        if (!module) { 
     48                osync_error_set(error, OSYNC_ERROR_GENERIC, "Couldn't load module from file %s", filename); 
     49                PyErr_Print(); 
     50                return NULL; 
     51        } 
     52        return module; 
     53} 
     54 
     55static PyObject *pm_make_change(PyObject *module, OSyncChange *change, OSyncError **error) 
     56{ 
     57        PyObject *pychg_cobject = PyCObject_FromVoidPtr(change, NULL); 
     58        if (!pychg_cobject) { 
     59                osync_error_set(error, OSYNC_ERROR_GENERIC, "Couldnt make pychg cobject"); 
     60                PyErr_Print(); 
     61                return NULL; 
     62        } 
     63         
     64        PyObject *pychg = PyObject_CallMethod(module, "OSyncChange", "O", pychg_cobject); 
     65        if (!pychg) { 
     66                osync_error_set(error, OSYNC_ERROR_GENERIC, "Cannot create Python OSyncChange"); 
     67                PyErr_Print(); 
     68                Py_XDECREF(pychg_cobject); 
     69                return NULL; 
     70        } 
     71        return pychg; 
     72} 
     73 
     74static PyObject *pm_make_context(PyObject *module, OSyncContext *ctx, OSyncError **error) 
     75{ 
     76        PyObject *pyctx_cobject = PyCObject_FromVoidPtr(ctx, NULL); 
     77        if (!pyctx_cobject) { 
     78                osync_error_set(error, OSYNC_ERROR_GENERIC, "Couldnt make pyctx cobject"); 
     79                PyErr_Print(); 
     80                return NULL; 
     81        } 
     82         
     83        PyObject *pyctx = PyObject_CallMethod(module, "OSyncContext", "O", pyctx_cobject); 
     84        if (!pyctx) { 
     85                osync_error_set(error, OSYNC_ERROR_GENERIC, "Cannot create Python OSyncContext"); 
     86                PyErr_Print(); 
     87                Py_XDECREF(pyctx_cobject); 
     88                return NULL; 
     89        } 
     90        return pyctx; 
     91} 
     92 
     93static PyObject *pm_make_member(PyObject *module, OSyncMember *member, OSyncError **error) 
     94{ 
     95        PyObject *pymember_cobject = PyCObject_FromVoidPtr(member, NULL); 
     96        if (!pymember_cobject) { 
     97                osync_error_set(error, OSYNC_ERROR_GENERIC, "Couldnt make pymember cobject"); 
     98                PyErr_Print(); 
     99                return NULL; 
     100        } 
     101         
     102        PyObject *pymember = PyObject_CallMethod(module, "OSyncMember", "O", pymember_cobject); 
     103        if (!pymember) { 
     104                osync_error_set(error, OSYNC_ERROR_GENERIC, "Cannot create Python OSyncMember"); 
     105                PyErr_Print(); 
     106                Py_XDECREF(pymember_cobject); 
     107                return NULL; 
     108        } 
     109        return pymember; 
    56110} 
    57111 
     
    61115 * has the other plugin methods (get_changeinfo, commit, etc.) 
    62116 */ 
    63 static void *py_initialize(OSyncMember *member, OSyncError **error) 
    64 { 
    65         char *name; 
    66         struct MemberData *data = malloc(sizeof(struct MemberData)); 
    67         if (!data) 
    68                 /*FIXME: set error info */ 
    69                 return NULL; 
    70  
    71         /* The plugin name was set on register_plugin() on plugin_data */ 
    72         name = osync_plugin_get_plugin_data(osync_member_get_plugin(member)); 
    73         if (!name) 
    74                 /*FIXME: set error info */ 
    75                 return NULL; 
     117static void *pm_initialize(OSyncMember *member, OSyncError **error) 
     118{ 
     119        const char *name = osync_member_get_plugindata(member); 
     120        if (!name) { 
     121                osync_error_set(error, OSYNC_ERROR_GENERIC, "No script name was set"); 
     122                return NULL; 
     123        } 
     124 
     125        MemberData *data = g_malloc(sizeof(MemberData)); 
    76126 
    77127        data->interp_thread = Py_NewInterpreter(); 
    78         if (0 && !data->interp_thread) { 
    79                 osync_debug("python", 1, "Couldn't initialize python interpreter"); 
     128        if (!data->interp_thread) { 
     129                osync_error_set(error, OSYNC_ERROR_GENERIC, "Couldn't initialize python sub interpreter"); 
    80130                goto error_free_data; 
    81131        } 
    82         if (change_sys_path() < 0) { 
    83                 osync_debug("python", 1, "Exception when initializing python intepreter"); 
    84                 PyErr_Print(); 
    85                 PyErr_Clear(); 
     132         
     133        if (!pm_load_opensync(error)) 
    86134                goto error_free_interp; 
    87         } 
    88         data->osync_module = PyImport_ImportModule("opensync"); 
    89         if (!data->module) { 
    90                 osync_debug("python", 1, "Couldn't load OpenSync module"); 
    91                 PyErr_Print(); 
    92                 PyErr_Clear(); 
     135         
     136        if (!(data->module = pm_load_script(name, error))) 
    93137                goto error_free_interp; 
    94         } 
    95         data->module = PyImport_ImportModule(name); 
    96         if (!data->module) { 
    97                 osync_debug("python", 1, "Couldn't load testmodule"); 
    98                 PyErr_Print(); 
    99                 PyErr_Clear(); 
    100                 goto error_unload_osync_mod; 
    101         } 
    102  
    103         /* Call the method */ 
    104         data->object = PyObject_CallMethod(data->module, "initialize", NULL); 
     138         
     139        PyObject *pymember = pm_make_member(data->module, member, error); 
     140        if (!pymember) 
     141                goto error_unload_module; 
     142         
     143        data->object = PyObject_CallMethod(data->module, "initialize", "O", pymember); 
    105144        if (!data->object) { 
    106                 osync_debug("python", 1, "Error during initialize()"); 
    107                 PyErr_Print(); 
    108                 PyErr_Clear(); 
     145                osync_error_set(error, OSYNC_ERROR_GENERIC, "Couldn't initialize module"); 
     146                PyErr_Print(); 
    109147                goto error_unload_module; 
    110148        } 
    111149 
    112         /* Done */ 
    113150        PyEval_ReleaseThread(data->interp_thread); 
    114151 
     
    117154error_unload_module: 
    118155        Py_DECREF(data->module); 
    119 error_unload_osync_mod: 
    120         Py_DECREF(data->osync_module); 
    121156error_free_interp: 
    122157        Py_EndInterpreter(data->interp_thread); 
     
    126161} 
    127162 
    128 static void py_finalize(void *data) 
    129 { 
    130         struct MemberData *mydata = data; 
     163static void pm_finalize(void *data) 
     164{ 
     165        osync_trace(TRACE_ENTRY, "%s(%p)", __func__, data); 
     166        MemberData *mydata = data; 
    131167        PyEval_AcquireThread(mydata->interp_thread); 
    132168        { 
    133169                PyObject *ret = PyObject_CallMethod(mydata->object, "finalize", NULL); 
    134170                if (!ret) { 
    135                         osync_debug("python", 1, "Error during finalize()"); 
     171                        osync_trace(TRACE_INTERNAL, "Error during finalize()"); 
    136172                        PyErr_Print(); 
    137                         PyErr_Clear(); 
    138173                } else 
    139174                        Py_DECREF(ret); 
     
    141176        Py_DECREF(mydata->object); 
    142177        Py_DECREF(mydata->module); 
    143         Py_DECREF(mydata->osync_module); 
     178        Py_EndInterpreter(mydata->interp_thread); 
     179         
    144180        free(mydata); 
    145  
    146         Py_EndInterpreter(mydata->interp_thread); 
    147 } 
    148  
    149 /** Create a new opensync.Change object for a given change */ 
    150 static PyObject *new_pychange(struct MemberData *mydata, OSyncChange *chg) 
    151 { 
    152         PyObject *cobject = NULL; 
    153         PyObject *ret = NULL; 
    154  
    155         cobject = PyCObject_FromVoidPtr(chg, NULL); 
    156         if (!cobject) 
    157                 goto error; 
    158  
    159         /* ret = opensync.Context(member=None, chg=cobject) */ 
    160         ret = PyObject_CallMethod(mydata->osync_module, "Change", "OO", Py_None, cobject); 
    161  
    162         /* Done, drop reference even on success (the opensync.Change object 
    163          * will hold a reference to the cobject) 
    164          */ 
    165         Py_XDECREF(cobject); 
    166  
    167         return ret; 
    168  
    169 error: 
    170         Py_XDECREF(ret); 
    171         Py_XDECREF(cobject); 
    172         return NULL; 
    173 } 
    174  
    175 /** Create a new opensync.Context object for a given context */ 
    176 static PyObject *new_pycontext(struct MemberData *mydata, OSyncContext *ctx) 
    177 { 
    178         PyObject *cobject = NULL; 
    179         PyObject *ret = NULL; 
    180  
    181         cobject = PyCObject_FromVoidPtr(ctx, NULL); 
    182         if (!cobject) 
    183                 goto error; 
    184  
    185         /* ret = opensync.Context(cobject) */ 
    186         ret = PyObject_CallMethod(mydata->osync_module, "Context", "O", cobject); 
    187  
    188         /* Done, drop reference even on success (the opensync.Context object 
    189          * will hold a reference to the cobject) 
    190          */ 
    191         Py_XDECREF(cobject); 
    192  
    193         return ret; 
    194  
    195 error: 
    196         Py_XDECREF(ret); 
    197         Py_XDECREF(cobject); 
    198         return NULL; 
     181        osync_trace(TRACE_EXIT, "%s", __func__); 
    199182} 
    200183 
     
    207190 * - function(context, change) 
    208191 */ 
    209 static void call_module_method(OSyncContext *ctx, OSyncChange *chg, char *name) 
    210 { 
    211         PyObject *context = NULL; 
     192static osync_bool pm_call_module_method(OSyncContext *ctx, OSyncChange *chg, char *name, OSyncError **error) 
     193{ 
     194        osync_trace(TRACE_ENTRY, "%s(%p, %p, %s, %p)", __func__, ctx, chg, name, error); 
     195        PyObject *pycontext = NULL; 
    212196        PyObject *ret = NULL; 
    213         PyObject *change = NULL; 
    214  
    215         struct MemberData *data = osync_context_get_plugin_data(ctx); 
     197 
     198        MemberData *data = osync_context_get_plugin_data(ctx); 
    216199        PyEval_AcquireThread(data->interp_thread); 
    217200 
     201        pycontext = pm_make_context(data->module, ctx, error); 
     202        if (!pycontext) { 
     203                PyEval_ReleaseThread(data->interp_thread); 
     204                osync_context_report_osyncerror(ctx, error); 
     205                osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); 
     206                return FALSE; 
     207        } 
     208 
    218209        if (chg) { 
    219                 change = new_pychange(data, chg); 
    220                 if (!change) { 
    221                         osync_debug("python", 1, "Can't create a change object"); 
    222                         PyErr_Print(); 
    223                         osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, "Couldn't create a opensync.Change object"); 
    224                         PyErr_Clear(); 
    225                         goto out; 
     210                PyObject *pychange = pm_make_change(data->module, chg, error); 
     211                if (!pychange) { 
     212                        PyEval_ReleaseThread(data->interp_thread); 
     213                        osync_context_report_osyncerror(ctx, error); 
     214                        osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); 
     215                        return FALSE; 
    226216                } 
    227         } 
    228  
    229         context = new_pycontext(data, ctx); 
    230         if (!context) { 
    231                 osync_debug("python", 1, "Can't create a context object"); 
    232                 PyErr_Print(); 
    233                 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, "Couldn't create a opensync.Context object"); 
    234                 PyErr_Clear(); 
    235                 goto out; 
    236         } 
    237  
    238         if (change) 
    239                 ret = PyObject_CallMethod(data->object, name, "OO", context, change); 
    240         else 
    241                 ret = PyObject_CallMethod(data->object, name, "O", context); 
    242  
     217                 
     218                ret = PyObject_CallMethod(data->object, name, "OO", pycontext, pychange); 
     219                 
     220                Py_XDECREF(pychange); 
     221        } else { 
     222                ret = PyObject_CallMethod(data->object, name, "O", pycontext); 
     223        } 
     224         
    243225        if (!ret) { 
    244                 osync_debug("python", 1, "Error during %s() method", name); 
    245                 PyErr_Print(); 
    246                 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, "Couldn't call python %s() method", name); 
    247                 PyErr_Clear(); 
    248                 goto out; 
    249         } 
    250  
    251 out: 
     226                osync_error_set(error, OSYNC_ERROR_GENERIC, "Error during %s() method", name); 
     227                PyErr_Print(); 
     228                PyEval_ReleaseThread(data->interp_thread); 
     229                osync_context_report_osyncerror(ctx, error); 
     230                osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); 
     231                return FALSE; 
     232        } 
     233 
    252234        Py_XDECREF(ret); 
    253         Py_XDECREF(change); 
    254         Py_XDECREF(context); 
    255235        PyEval_ReleaseThread(data->interp_thread); 
    256 } 
    257  
    258 static void py_connect(OSyncContext *ctx) 
    259 { 
    260         call_module_method(ctx, NULL, "connect"); 
    261 } 
    262  
    263  
    264 static void py_get_changeinfo(OSyncContext *ctx) 
    265 { 
    266         call_module_method(ctx, NULL, "get_changeinfo"); 
    267 } 
    268  
    269  
    270 static void py_get_data(OSyncContext *ctx, OSyncChange *change) 
    271 { 
    272         call_module_method(ctx, change, "get_data"); 
    273 } 
    274  
    275 static osync_bool py_access(OSyncContext *ctx, OSyncChange *change) 
    276 { 
    277         call_module_method(ctx, change, "access"); 
     236         
     237        osync_trace(TRACE_EXIT, "%s", __func__); 
    278238        return TRUE; 
    279239} 
    280240 
    281 static osync_bool py_commit_change(OSyncContext *ctx, OSyncChange *change) 
    282 { 
    283         call_module_method(ctx, change, "commit_change"); 
    284         return 0; 
    285 } 
    286  
    287 static void py_sync_done(OSyncContext *ctx) 
    288 { 
    289         call_module_method(ctx, NULL, "sync_done"); 
    290 } 
    291  
    292 static void py_disconnect(OSyncContext *ctx) 
    293 { 
    294         call_module_method(ctx, NULL, "disconnect"); 
     241static void pm_connect(OSyncContext *ctx) 
     242{ 
     243        osync_trace(TRACE_ENTRY, "%s(%p)", __func__, ctx); 
     244        OSyncError *error = NULL; 
     245        pm_call_module_method(ctx, NULL, "connect", &error); 
     246        osync_trace(TRACE_EXIT, "%s", __func__); 
     247} 
     248 
     249 
     250static void pm_get_changeinfo(OSyncContext *ctx) 
     251{ 
     252        osync_trace(TRACE_ENTRY, "%s(%p)", __func__, ctx); 
     253        OSyncError *error = NULL; 
     254        pm_call_module_method(ctx, NULL, "get_changeinfo", &error); 
     255        osync_trace(TRACE_EXIT, "%s", __func__); 
     256} 
     257 
     258static osync_bool pm_access(OSyncContext *ctx, OSyncChange *change) 
     259{        
     260        osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, ctx, change); 
     261        OSyncError *error = NULL; 
     262        pm_call_module_method(ctx, change, "access", &error); 
     263        osync_trace(TRACE_EXIT, "%s", __func__); 
     264        return TRUE; 
     265} 
     266 
     267static osync_bool pm_commit_change(OSyncContext *ctx, OSyncChange *change) 
     268{        
     269        osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, ctx, change); 
     270        OSyncError *error = NULL; 
     271        pm_call_module_method(ctx, change, "commit_change", &error); 
     272        osync_trace(TRACE_EXIT, "%s", __func__); 
     273        return TRUE; 
     274} 
     275 
     276static void pm_sync_done(OSyncContext *ctx) 
     277{ 
     278        osync_trace(TRACE_ENTRY, "%s(%p)", __func__, ctx); 
     279        OSyncError *error = NULL; 
     280        pm_call_module_method(ctx, NULL, "sync_done", &error); 
     281        osync_trace(TRACE_EXIT, "%s", __func__); 
     282} 
     283 
     284static void pm_disconnect(OSyncContext *ctx) 
     285{ 
     286        osync_trace(TRACE_ENTRY, "%s(%p)", __func__, ctx); 
     287        OSyncError *error = NULL; 
     288        pm_call_module_method(ctx, NULL, "disconnect", &error); 
     289        osync_trace(TRACE_EXIT, "%s", __func__); 
    295290} 
    296291 
     
    302297 *       accepted objtypes/formats info) 
    303298 */ 
    304 static int register_plugin(OSyncEnv *env, PyObject *osync_module, char *name) 
    305 { 
    306         PyObject *module = NULL; 
    307         PyObject *get_info_result = NULL; 
    308         PythonPluginInfo pyinfo; 
    309         PyObject *pyinfo_cobject = NULL; 
    310         PyObject *get_info_parm = NULL; 
    311         OSyncPluginInfo *info; 
    312         int ret = -1; 
    313  
    314         osync_trace(TRACE_ENTRY, "register_plugin"); 
    315  
    316         module = PyImport_ImportModule(name); 
     299static osync_bool register_plugin(OSyncEnv *env, const char *filename, OSyncError **error) 
     300{ 
     301        osync_trace(TRACE_ENTRY, "%s(%p, %s, %p)", __func__, env, filename, error); 
     302 
     303        PyObject *module = pm_load_script(filename, error); 
    317304        if (!module) { 
    318                 osync_debug("python", 1, "Couldn't load testmodule"); 
     305                osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); 
     306                return FALSE; 
     307        } 
     308         
     309        OSyncPluginInfo *info = osync_plugin_new_info(env); 
     310        info->functions.initialize = pm_initialize; 
     311        info->functions.connect = pm_connect; 
     312        info->functions.get_changeinfo = pm_get_changeinfo; 
     313        info->functions.sync_done = pm_sync_done; 
     314        info->functions.disconnect = pm_disconnect; 
     315        info->functions.finalize = pm_finalize; 
     316         
     317        info->plugin_data = g_strdup(filename); 
     318         
     319        PyObject *pyinfo_cobject = PyCObject_FromVoidPtr(info, NULL); 
     320        if (!pyinfo_cobject) { 
     321                osync_error_set(error, OSYNC_ERROR_GENERIC, "Couldnt make pyinfo cobject"); 
    319322                PyErr_Print(); 
    320323                PyErr_Clear(); 
    321                 goto out; 
    322         } 
    323  
    324         info = osync_plugin_new_info(env); 
    325         if (!info) { 
    326                 osync_debug("python", 1, "Couldn't create a new plugin object"); 
    327                 goto error; 
    328         } 
    329  
    330         info->functions.initialize = py_initialize; 
    331         info->functions.connect = py_connect; 
    332         info->functions.sync_done = py_sync_done; 
    333         info->functions.disconnect = py_disconnect; 
    334         info->functions.finalize = py_finalize; 
    335         info->functions.get_changeinfo = py_get_changeinfo; 
    336         info->functions.get_data = py_get_data; 
    337          
    338         /*TODO: let the module get_info function fill the fields below: */ 
    339         info->is_threadsafe = 1; 
    340  
    341         /* The plugin data is just the plugin name, 
    342          * to be used on py_initialize() 
    343          */ 
    344         info->plugin_data = strdup(name); 
    345          
    346         /** Build a PluginInfo object for use by get_info */ 
    347         pyinfo.commit_fn = py_commit_change; 
    348         pyinfo.access_fn = py_access; 
    349         pyinfo.osync_info = info; 
    350  
    351         pyinfo_cobject = PyCObject_FromVoidPtr(&pyinfo, NULL); 
    352         if (!pyinfo_cobject) { 
    353                 osync_debug("python", 1, "Can't create pyinfo_cobject"); 
     324                osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); 
     325                return FALSE; 
     326        } 
     327         
     328        PyObject *pyinfo = PyObject_CallMethod(module, "OSyncPluginInfo", "O", pyinfo_cobject); 
     329        osync_trace(TRACE_INTERNAL, "pyinfo: %p\n", pyinfo); 
     330        if (!pyinfo) { 
     331                osync_error_set(error, OSYNC_ERROR_GENERIC, "Cannot create Python OSyncPluginInfo"); 
    354332                PyErr_Print(); 
    355333                PyErr_Clear(); 
    356                 goto error_cancel_register; 
    357         } 
    358  
    359         /* get_info_parm = opensync.PluginInfo(pyinfo_cobject) */ 
    360         get_info_parm = PyObject_CallMethod(osync_module, "PluginInfo", "O", pyinfo_cobject); 
    361         if (!get_info_parm) { 
    362                 osync_debug("python", 1, "Can't create get_info_parm"); 
     334                osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); 
     335                return FALSE; 
     336        } 
     337         
     338        if (!PyObject_CallMethod(module, "get_info", "O", pyinfo)) { 
     339                osync_error_set(error, OSYNC_ERROR_GENERIC, "Error calling get_info"); 
    363340                PyErr_Print(); 
    364341                PyErr_Clear(); 
    365                 goto error_cancel_register; 
    366         } 
    367         /* Call get_info */ 
    368         get_info_result = PyObject_CallMethod(module, "get_info", "O", get_info_parm); 
    369         if (!get_info_result) { 
    370                 osync_debug("python", 1, "Error during initialize()"); 
    371                 PyErr_Print(); 
    372                 PyErr_Clear(); 
    373                 goto error_cancel_register; 
    374         } 
    375  
     342                osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); 
     343                return FALSE; 
     344        } 
     345         
    376346        if (!info->name) { 
    377347                osync_debug("python", 1, "The plugin didn't set its name!"); 
    378                 goto error_cancel_register; 
    379         } 
    380  
    381         osync_trace(TRACE_EXI