You can subscribe to this list here.
2003 |
Jan
|
Feb
|
Mar
(35) |
Apr
(15) |
May
(46) |
Jun
(17) |
Jul
(11) |
Aug
(7) |
Sep
|
Oct
|
Nov
(6) |
Dec
|
---|
From: <gb...@us...> - 2003-11-05 02:43:32
|
Update of /cvsroot/zxsync/zXSync/plugins/zaurus In directory sc8-pr-cvs1:/tmp/cvs-serv14983 Modified Files: zauruscalendar.py Log Message: more field fixes required to land iCal support. Index: zauruscalendar.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/zaurus/zauruscalendar.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** zauruscalendar.py 4 Nov 2003 23:49:17 -0000 1.3 --- zauruscalendar.py 5 Nov 2003 02:43:28 -0000 1.4 *************** *** 78,81 **** --- 78,82 ---- for entry in entries: vevent = VEvent(entry['uid']) + vevent.addField("X-ZXSYNC-ZAURUS-UID", entry['uid']) if entry.has_key('description'): vevent.addField("SUMMARY",entry['description']) |
From: <gb...@us...> - 2003-11-05 02:43:31
|
Update of /cvsroot/zxsync/zXSync/plugins/zaurus/util In directory sc8-pr-cvs1:/tmp/cvs-serv14983/util Modified Files: datebook.py Log Message: more field fixes required to land iCal support. Index: datebook.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/zaurus/util/datebook.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** datebook.py 13 May 2003 17:58:15 -0000 1.6 --- datebook.py 5 Nov 2003 02:43:28 -0000 1.7 *************** *** 188,191 **** --- 188,192 ---- def xmlFromICAL( entry, rid, zaurus ): """Return a zaurus-style XML entry from a representation of an icalendar entry""" + # XXX TODO: map UIDs properly! uid = entry.getField("UID") startdt = entry.getField("DTSTART") *************** *** 205,209 **** # this doesn't look elegant, but it's because I don't know of any c-style assignment shortcut # and I wish to avoid multiple costly getField calls ! zcat = entry.getField("X-ZAURUS-CATEGORY") icalendar = None catField = None --- 206,210 ---- # this doesn't look elegant, but it's because I don't know of any c-style assignment shortcut # and I wish to avoid multiple costly getField calls ! zcat = entry.getField("X-ZXSYNC-ZAURUS-CATEGORY") icalendar = None catField = None *************** *** 212,216 **** else: # XXX: TODO: make this field configurable ! icalendar = entry.getField("X-ICAL-CALENDAR") if( icalendar ): catField = " categories=\"" + str(zaurus.categories[zaurus.categoryMap[icalendar]]) + "\"" --- 213,217 ---- else: # XXX: TODO: make this field configurable ! icalendar = entry.getField("X-ZXSYNC-ICAL-CALENDAR") if( icalendar ): catField = " categories=\"" + str(zaurus.categories[zaurus.categoryMap[icalendar]]) + "\"" *************** *** 225,229 **** xmlEntry += " uid=\""+str(uid)+"\"" xmlEntry += " rid=\""+str(rid)+"\"" ! rinfo = entry.getField("X-ZAURUS-RINFO") if( rinfo ): xmlEntry += " rinfo=\"" + str( rinfo ) + "\"" --- 226,230 ---- xmlEntry += " uid=\""+str(uid)+"\"" xmlEntry += " rid=\""+str(rid)+"\"" ! rinfo = entry.getField("X-ZXSYNC-ZAURUS-RINFO") if( rinfo ): xmlEntry += " rinfo=\"" + str( rinfo ) + "\"" |
From: <gb...@us...> - 2003-11-05 00:08:14
|
Update of /cvsroot/zxsync/zXSync/uuidmodule In directory sc8-pr-cvs1:/tmp/cvs-serv23514 Added Files: uuidgen.py uuidgen_wrap.c Log Message: adding SWIG-generated files so that SWIG is not a prerequisite for building zXSync unless you change something here (which should be rare!) --- NEW FILE: uuidgen.py --- # This file was created automatically by SWIG. # Don't modify this file, modify the SWIG interface instead. # This file is compatible with both classic and new-style classes. import _uuidgen def _swig_setattr(self,class_type,name,value): if (name == "this"): if isinstance(value, class_type): self.__dict__[name] = value.this if hasattr(value,"thisown"): self.__dict__["thisown"] = value.thisown del value.thisown return method = class_type.__swig_setmethods__.get(name,None) if method: return method(self,value) self.__dict__[name] = value def _swig_getattr(self,class_type,name): method = class_type.__swig_getmethods__.get(name,None) if method: return method(self) raise AttributeError,name import types try: _object = types.ObjectType _newclass = 1 except AttributeError: class _object : pass _newclass = 0 newUUID = _uuidgen.newUUID --- NEW FILE: uuidgen_wrap.c --- /* ---------------------------------------------------------------------------- * This file was automatically generated by SWIG (http://www.swig.org). * Version 1.3.16u-20030618-0517 * * This file is not intended to be easily readable and contains a number of * coding conventions designed to improve portability and efficiency. Do not make * changes to this file unless you know what you are doing--modify the SWIG * interface file instead. * ----------------------------------------------------------------------------- */ #define SWIGPYTHON #include "Python.h" /*********************************************************************** * common.swg * * This file contains generic SWIG runtime support for pointer * type checking as well as a few commonly used macros to control * external linkage. * * Author : David Beazley (be...@cs...) * * Copyright (c) 1999-2000, The University of Chicago * * This file may be freely redistributed without license or fee provided * this copyright message remains intact. ************************************************************************/ #include <string.h> #if defined(_WIN32) || defined(__WIN32__) # if defined(_MSC_VER) # if defined(STATIC_LINKED) # define SWIGEXPORT(a) a # define SWIGIMPORT(a) extern a # else # define SWIGEXPORT(a) __declspec(dllexport) a # define SWIGIMPORT(a) extern a # endif # else # if defined(__BORLANDC__) # define SWIGEXPORT(a) a _export # define SWIGIMPORT(a) a _export # else # define SWIGEXPORT(a) a # define SWIGIMPORT(a) a # endif # endif #else # define SWIGEXPORT(a) a # define SWIGIMPORT(a) a #endif #ifdef SWIG_GLOBAL #define SWIGRUNTIME(a) SWIGEXPORT(a) #else #define SWIGRUNTIME(a) static a #endif #ifdef __cplusplus extern "C" { #endif typedef void *(*swig_converter_func)(void *); typedef struct swig_type_info *(*swig_dycast_func)(void **); typedef struct swig_type_info { const char *name; swig_converter_func converter; const char *str; void *clientdata; swig_dycast_func dcast; struct swig_type_info *next; struct swig_type_info *prev; } swig_type_info; #ifdef SWIG_NOINCLUDE SWIGIMPORT(swig_type_info *) SWIG_TypeRegister(swig_type_info *); SWIGIMPORT(swig_type_info *) SWIG_TypeCheck(char *c, swig_type_info *); SWIGIMPORT(void *) SWIG_TypeCast(swig_type_info *, void *); SWIGIMPORT(swig_type_info *) SWIG_TypeDynamicCast(swig_type_info *, void **); SWIGIMPORT(swig_type_info *) SWIG_TypeQuery(const char *); SWIGIMPORT(void) SWIG_TypeClientData(swig_type_info *, void *); #else static swig_type_info *swig_type_list = 0; /* Register a type mapping with the type-checking */ SWIGRUNTIME(swig_type_info *) SWIG_TypeRegister(swig_type_info *ti) { swig_type_info *tc, *head, *ret, *next; /* Check to see if this type has already been registered */ tc = swig_type_list; while (tc) { if (strcmp(tc->name, ti->name) == 0) { /* Already exists in the table. Just add additional types to the list */ if (tc->clientdata) ti->clientdata = tc->clientdata; head = tc; next = tc->next; goto l1; } tc = tc->prev; } head = ti; next = 0; /* Place in list */ ti->prev = swig_type_list; swig_type_list = ti; /* Build linked lists */ l1: ret = head; tc = ti + 1; /* Patch up the rest of the links */ while (tc->name) { head->next = tc; tc->prev = head; head = tc; tc++; } head->next = next; return ret; } /* Check the typename */ SWIGRUNTIME(swig_type_info *) SWIG_TypeCheck(char *c, swig_type_info *ty) { swig_type_info *s; if (!ty) return 0; /* Void pointer */ s = ty->next; /* First element always just a name */ do { if (strcmp(s->name,c) == 0) { if (s == ty->next) return s; /* Move s to the top of the linked list */ s->prev->next = s->next; if (s->next) { s->next->prev = s->prev; } /* Insert s as second element in the list */ s->next = ty->next; if (ty->next) ty->next->prev = s; ty->next = s; return s; } s = s->next; } while (s && (s != ty->next)); return 0; } /* Cast a pointer up an inheritance hierarchy */ SWIGRUNTIME(void *) SWIG_TypeCast(swig_type_info *ty, void *ptr) { if ((!ty) || (!ty->converter)) return ptr; return (*ty->converter)(ptr); } /* Dynamic pointer casting. Down an inheritance hierarchy */ SWIGRUNTIME(swig_type_info *) SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) { swig_type_info *lastty = ty; if (!ty || !ty->dcast) return ty; while (ty && (ty->dcast)) { ty = (*ty->dcast)(ptr); if (ty) lastty = ty; } return lastty; } /* Search for a swig_type_info structure */ SWIGRUNTIME(swig_type_info *) SWIG_TypeQuery(const char *name) { swig_type_info *ty = swig_type_list; while (ty) { if (ty->str && (strcmp(name,ty->str) == 0)) return ty; if (ty->name && (strcmp(name,ty->name) == 0)) return ty; ty = ty->prev; } return 0; } /* Set the clientdata field for a type */ SWIGRUNTIME(void) SWIG_TypeClientData(swig_type_info *ti, void *clientdata) { swig_type_info *tc, *equiv; if (ti->clientdata) return; ti->clientdata = clientdata; equiv = ti->next; while (equiv) { if (!equiv->converter) { tc = swig_type_list; while (tc) { if ((strcmp(tc->name, equiv->name) == 0)) SWIG_TypeClientData(tc,clientdata); tc = tc->prev; } } equiv = equiv->next; } } #endif #ifdef __cplusplus } #endif /*********************************************************************** * python.swg * * This file contains the runtime support for Python modules * and includes code for managing global variables and pointer * type checking. * * Author : David Beazley (be...@cs...) ************************************************************************/ #include "Python.h" #ifdef __cplusplus extern "C" { #endif #define SWIG_PY_INT 1 #define SWIG_PY_FLOAT 2 #define SWIG_PY_STRING 3 #define SWIG_PY_POINTER 4 #define SWIG_PY_BINARY 5 /* Flags for pointer conversion */ #define SWIG_POINTER_EXCEPTION 0x1 #define SWIG_POINTER_DISOWN 0x2 /* Exception handling in wrappers */ #define SWIG_fail goto fail /* Constant information structure */ typedef struct swig_const_info { int type; char *name; long lvalue; double dvalue; void *pvalue; swig_type_info **ptype; } swig_const_info; #ifdef SWIG_NOINCLUDE SWIGEXPORT(PyObject *) SWIG_newvarlink(); SWIGEXPORT(void) SWIG_addvarlink(PyObject *, char *, PyObject *(*)(void), int (*)(PyObject *)); SWIGEXPORT(int) SWIG_ConvertPtr(PyObject *, void **, swig_type_info *, int); SWIGEXPORT(int) SWIG_ConvertPacked(PyObject *, void *, int sz, swig_type_info *, int); SWIGEXPORT(char *) SWIG_PackData(char *c, void *, int); SWIGEXPORT(char *) SWIG_UnpackData(char *c, void *, int); SWIGEXPORT(PyObject *) SWIG_NewPointerObj(void *, swig_type_info *,int own); SWIGEXPORT(PyObject *) SWIG_NewPackedObj(void *, int sz, swig_type_info *); SWIGEXPORT(void) SWIG_InstallConstants(PyObject *d, swig_const_info constants[]); #else /* ----------------------------------------------------------------------------- * global variable support code. * ----------------------------------------------------------------------------- */ typedef struct swig_globalvar { char *name; /* Name of global variable */ PyObject *(*get_attr)(void); /* Return the current value */ int (*set_attr)(PyObject *); /* Set the value */ struct swig_globalvar *next; } swig_globalvar; typedef struct swig_varlinkobject { PyObject_HEAD swig_globalvar *vars; } swig_varlinkobject; static PyObject * swig_varlink_repr(swig_varlinkobject *v) { v = v; return PyString_FromString("<Global variables>"); } static int swig_varlink_print(swig_varlinkobject *v, FILE *fp, int flags) { swig_globalvar *var; flags = flags; fprintf(fp,"Global variables { "); for (var = v->vars; var; var=var->next) { fprintf(fp,"%s", var->name); if (var->next) fprintf(fp,", "); } fprintf(fp," }\n"); return 0; } static PyObject * swig_varlink_getattr(swig_varlinkobject *v, char *n) { swig_globalvar *var = v->vars; while (var) { if (strcmp(var->name,n) == 0) { return (*var->get_attr)(); } var = var->next; } PyErr_SetString(PyExc_NameError,"Unknown C global variable"); return NULL; } static int swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) { swig_globalvar *var = v->vars; while (var) { if (strcmp(var->name,n) == 0) { return (*var->set_attr)(p); } var = var->next; } PyErr_SetString(PyExc_NameError,"Unknown C global variable"); return 1; } statichere PyTypeObject varlinktype = { PyObject_HEAD_INIT(0) 0, (char *)"swigvarlink", /* Type name */ sizeof(swig_varlinkobject), /* Basic size */ 0, /* Itemsize */ 0, /* Deallocator */ (printfunc) swig_varlink_print, /* Print */ (getattrfunc) swig_varlink_getattr, /* get attr */ (setattrfunc) swig_varlink_setattr, /* Set attr */ 0, /* tp_compare */ (reprfunc) swig_varlink_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_mapping*/ 0, /* tp_hash */ }; /* Create a variable linking object for use later */ SWIGRUNTIME(PyObject *) SWIG_newvarlink(void) { swig_varlinkobject *result = 0; result = PyMem_NEW(swig_varlinkobject,1); varlinktype.ob_type = &PyType_Type; /* Patch varlinktype into a PyType */ result->ob_type = &varlinktype; result->vars = 0; result->ob_refcnt = 0; Py_XINCREF((PyObject *) result); return ((PyObject*) result); } SWIGRUNTIME(void) SWIG_addvarlink(PyObject *p, char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) { swig_varlinkobject *v; swig_globalvar *gv; v= (swig_varlinkobject *) p; gv = (swig_globalvar *) malloc(sizeof(swig_globalvar)); gv->name = (char *) malloc(strlen(name)+1); strcpy(gv->name,name); gv->get_attr = get_attr; gv->set_attr = set_attr; gv->next = v->vars; v->vars = gv; } /* Pack binary data into a string */ SWIGRUNTIME(char *) SWIG_PackData(char *c, void *ptr, int sz) { static char hex[17] = "0123456789abcdef"; int i; unsigned char *u = (unsigned char *) ptr; register unsigned char uu; for (i = 0; i < sz; i++,u++) { uu = *u; *(c++) = hex[(uu & 0xf0) >> 4]; *(c++) = hex[uu & 0xf]; } return c; } /* Unpack binary data from a string */ SWIGRUNTIME(char *) SWIG_UnpackData(char *c, void *ptr, int sz) { register unsigned char uu = 0; register int d; unsigned char *u = (unsigned char *) ptr; int i; for (i = 0; i < sz; i++, u++) { d = *(c++); if ((d >= '0') && (d <= '9')) uu = ((d - '0') << 4); else if ((d >= 'a') && (d <= 'f')) uu = ((d - ('a'-10)) << 4); d = *(c++); if ((d >= '0') && (d <= '9')) uu |= (d - '0'); else if ((d >= 'a') && (d <= 'f')) uu |= (d - ('a'-10)); *u = uu; } return c; } /* Convert a pointer value */ SWIGRUNTIME(int) SWIG_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags) { swig_type_info *tc; char *c; static PyObject *SWIG_this = 0; int newref = 0; PyObject *pyobj = 0; if (!obj) return 0; if (obj == Py_None) { *ptr = 0; return 0; } #ifdef SWIG_COBJECT_TYPES if (!(PyCObject_Check(obj))) { if (!SWIG_this) SWIG_this = PyString_FromString("this"); pyobj = obj; obj = PyObject_GetAttr(obj,SWIG_this); newref = 1; if (!obj) goto type_error; if (!PyCObject_Check(obj)) { Py_DECREF(obj); goto type_error; } } *ptr = PyCObject_AsVoidPtr(obj); c = (char *) PyCObject_GetDesc(obj); if (newref) Py_DECREF(obj); goto cobject; #else if (!(PyString_Check(obj))) { if (!SWIG_this) SWIG_this = PyString_FromString("this"); pyobj = obj; obj = PyObject_GetAttr(obj,SWIG_this); newref = 1; if (!obj) goto type_error; if (!PyString_Check(obj)) { Py_DECREF(obj); goto type_error; } } c = PyString_AsString(obj); /* Pointer values must start with leading underscore */ if (*c != '_') { *ptr = (void *) 0; if (strcmp(c,"NULL") == 0) { if (newref) { Py_DECREF(obj); } return 0; } else { if (newref) { Py_DECREF(obj); } goto type_error; } } c++; c = SWIG_UnpackData(c,ptr,sizeof(void *)); if (newref) { Py_DECREF(obj); } #endif #ifdef SWIG_COBJECT_TYPES cobject: #endif if (ty) { tc = SWIG_TypeCheck(c,ty); if (!tc) goto type_error; *ptr = SWIG_TypeCast(tc,(void*) *ptr); } if ((pyobj) && (flags & SWIG_POINTER_DISOWN)) { PyObject *zero = PyInt_FromLong(0); PyObject_SetAttrString(pyobj,(char*)"thisown",zero); Py_DECREF(zero); } return 0; type_error: if (flags & SWIG_POINTER_EXCEPTION) { if (ty) { char *temp = (char *) malloc(64+strlen(ty->name)); sprintf(temp,"Type error. Expected %s", ty->name); PyErr_SetString(PyExc_TypeError, temp); free((char *) temp); } else { PyErr_SetString(PyExc_TypeError,"Expected a pointer"); } } return -1; } /* Convert a packed value value */ SWIGRUNTIME(int) SWIG_ConvertPacked(PyObject *obj, void *ptr, int sz, swig_type_info *ty, int flags) { swig_type_info *tc; char *c; if ((!obj) || (!PyString_Check(obj))) goto type_error; c = PyString_AsString(obj); /* Pointer values must start with leading underscore */ if (*c != '_') goto type_error; c++; c = SWIG_UnpackData(c,ptr,sz); if (ty) { tc = SWIG_TypeCheck(c,ty); if (!tc) goto type_error; } return 0; type_error: if (flags) { if (ty) { char *temp = (char *) malloc(64+strlen(ty->name)); sprintf(temp,"Type error. Expected %s", ty->name); PyErr_SetString(PyExc_TypeError, temp); free((char *) temp); } else { PyErr_SetString(PyExc_TypeError,"Expected a pointer"); } } return -1; } /* Create a new pointer object */ SWIGRUNTIME(PyObject *) SWIG_NewPointerObj(void *ptr, swig_type_info *type, int own) { PyObject *robj; if (!ptr) { Py_INCREF(Py_None); return Py_None; } #ifdef SWIG_COBJECT_TYPES robj = PyCObject_FromVoidPtrAndDesc((void *) ptr, (char *) type->name, NULL); #else { char result[1024]; char *r = result; *(r++) = '_'; r = SWIG_PackData(r,&ptr,sizeof(void *)); strcpy(r,type->name); robj = PyString_FromString(result); } #endif if (!robj || (robj == Py_None)) return robj; if (type->clientdata) { PyObject *inst; PyObject *args = Py_BuildValue((char*)"(O)", robj); Py_DECREF(robj); inst = PyObject_CallObject((PyObject *) type->clientdata, args); Py_DECREF(args); if (inst) { if (own) { PyObject *n = PyInt_FromLong(1); PyObject_SetAttrString(inst,(char*)"thisown",n); Py_DECREF(n); } robj = inst; } } return robj; } SWIGRUNTIME(PyObject *) SWIG_NewPackedObj(void *ptr, int sz, swig_type_info *type) { char result[1024]; char *r = result; if ((2*sz + 1 + strlen(type->name)) > 1000) return 0; *(r++) = '_'; r = SWIG_PackData(r,ptr,sz); strcpy(r,type->name); return PyString_FromString(result); } /* Install Constants */ SWIGRUNTIME(void) SWIG_InstallConstants(PyObject *d, swig_const_info constants[]) { int i; PyObject *obj; for (i = 0; constants[i].type; i++) { switch(constants[i].type) { case SWIG_PY_INT: obj = PyInt_FromLong(constants[i].lvalue); break; case SWIG_PY_FLOAT: obj = PyFloat_FromDouble(constants[i].dvalue); break; case SWIG_PY_STRING: obj = PyString_FromString((char *) constants[i].pvalue); break; case SWIG_PY_POINTER: obj = SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0); break; case SWIG_PY_BINARY: obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype)); break; default: obj = 0; break; } if (obj) { PyDict_SetItemString(d,constants[i].name,obj); Py_DECREF(obj); } } } #endif #ifdef __cplusplus } #endif /* -------- TYPES TABLE (BEGIN) -------- */ static swig_type_info *swig_types[1]; /* -------- TYPES TABLE (END) -------- */ /*----------------------------------------------- @(target):= _uuidgen.so ------------------------------------------------*/ #define SWIG_init init_uuidgen #define SWIG_name "_uuidgen" #include "uuidgen.h" #ifdef __cplusplus extern "C" { #endif static PyObject *_wrap_newUUID(PyObject *self, PyObject *args) { PyObject *resultobj; char *result; if(!PyArg_ParseTuple(args,(char *)":newUUID")) goto fail; result = (char *)newUUID(); resultobj = result ? PyString_FromString(result) : Py_BuildValue((char*)""); return resultobj; fail: return NULL; } static PyMethodDef SwigMethods[] = { { (char *)"newUUID", _wrap_newUUID, METH_VARARGS }, { NULL, NULL } }; /* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */ static swig_type_info *swig_types_initial[] = { 0 }; /* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */ static swig_const_info swig_const_table[] = { {0}}; #ifdef __cplusplus } #endif #ifdef __cplusplus extern "C" #endif SWIGEXPORT(void) SWIG_init(void) { static PyObject *SWIG_globals = 0; static int typeinit = 0; PyObject *m, *d; int i; if (!SWIG_globals) SWIG_globals = SWIG_newvarlink(); m = Py_InitModule((char *) SWIG_name, SwigMethods); d = PyModule_GetDict(m); if (!typeinit) { for (i = 0; swig_types_initial[i]; i++) { swig_types[i] = SWIG_TypeRegister(swig_types_initial[i]); } typeinit = 1; } SWIG_InstallConstants(d,swig_const_table); } |
From: <gb...@us...> - 2003-11-05 00:03:19
|
Update of /cvsroot/zxsync/zXSync/uuidmodule In directory sc8-pr-cvs1:/tmp/cvs-serv22324 Added Files: Makefile uuid-test.py uuidgen.c uuidgen.h Log Message: adding python binding to CoreFoundation's UUID generation routine for use with iCal --- NEW FILE: Makefile --- # a quick and dirty makefile because I can't get xcode to build this properly # # Copyright (C) 2003 Geoff Beier <me...@mo...> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # $Id: Makefile,v 1.1 2003/11/05 00:03:16 gbeier Exp $ # MODULE=uuidgen PYTHON_HEADERLOC=/System/Library/Frameworks/Python.framework/Versions/2.3/include/python2.3 SWIG=/sw/bin/swig SWIGFLAGS=-python PYTHON=/usr/bin/python FRAMEWORKS=-framework Python -framework CoreFoundation CFLAGS+= -I $(PYTHON_HEADERLOC) LDFLAGS=-bundle -bundle_loader $(PYTHON) $(FRAMEWORKS) OBJS=$(MODULE).o $(MODULE)_wrap.o all: _$(MODULE).so $(MODULE)_wrap.c: $(MODULE).h $(SWIG) $(SWIGFLAGS) $(MODULE).h _$(MODULE).so: $(OBJS) $(CC) $(LDFLAGS) $(OBJS) -o _$(MODULE).so clean: rm -f $(OBJS) _$(MODULE).so $(MODULE).py $(MODULE)_wrap.c *.pyc viclean: rm -f *~ --- NEW FILE: uuid-test.py --- #!/usr/bin/env python # # test for python CFUUID binding # # Copyright (C) 2003 Geoff Beier <me...@mo...> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # $Id: uuid-test.py,v 1.1 2003/11/05 00:03:16 gbeier Exp $ # import uuidgen print "CFUUID generated ", uuidgen.newUUID() --- NEW FILE: uuidgen.c --- /* * uuidgen.c - a simple wrapper for the CFUUIDCreate() function so that it can easily be * used with python * * Copyright (C) 2003 Geoff Beier <me...@mo...> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: uuidgen.c,v 1.1 2003/11/05 00:03:16 gbeier Exp $ * */ #include "uuidgen.h" #include <CoreFoundation/CoreFoundation.h> /* * generates a UUID and returns it as a C-style string */ char * newUUID() { char * rv = NULL; CFStringRef uuidString = NULL; CFUUIDRef uuid = NULL; CFIndex len = 0; uuid = CFUUIDCreate( NULL ); if( NULL == uuid ) { return rv; } uuidString = CFUUIDCreateString( NULL, uuid ); if( NULL == uuidString ) { return rv; } len = CFStringGetLength( uuidString ); rv = malloc( (size_t)(len * sizeof(char) + 1) ); if( NULL == rv ) { return rv; } if( !CFStringGetCString( uuidString, rv, len * sizeof(char) + 1, kCFStringEncodingASCII ) ) { free( rv ); rv = NULL; } return rv; } --- NEW FILE: uuidgen.h --- /* * uuidgen.h - python interface to CF UUID function * * * Copyright (C) 2003 Geoff Beier <me...@mo...> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: uuidgen.h,v 1.1 2003/11/05 00:03:16 gbeier Exp $ * */ /*************** SWIG stuff ***************/ #ifdef SWIG %module uuidgen %{ #include "uuidgen.h" %} #endif /****************************************/ /** * newUUID() - uses CF to generate a new UUID and convert it to a C-style string * if my carbon-fu were better I should just wrap the CF stuff up (extend the CF * bridge from MacPython 2.3 and maybe submit a patch to the python crew...) but * this + SWIG is more my speed right now. */ char * newUUID( void ); |
From: <gb...@us...> - 2003-11-04 23:51:01
|
Update of /cvsroot/zxsync/zXSync/uuidmodule In directory sc8-pr-cvs1:/tmp/cvs-serv20582/uuidmodule Log Message: Directory /cvsroot/zxsync/zXSync/uuidmodule added to the repository |
From: <gb...@us...> - 2003-11-04 23:49:20
|
Update of /cvsroot/zxsync/zXSync/plugins/zaurus In directory sc8-pr-cvs1:/tmp/cvs-serv20082 Modified Files: zauruscalendar.py Log Message: changing custom properties from X-* to X-ZXSYNC-* in preparation for iCal merge Index: zauruscalendar.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/zaurus/zauruscalendar.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** zauruscalendar.py 6 May 2003 17:32:13 -0000 1.2 --- zauruscalendar.py 4 Nov 2003 23:49:17 -0000 1.3 *************** *** 105,109 **** # only add the z plugin "category" field if it's not blank if( entry['categories'] ): ! vevent.addField("X-ZAURUS-CATEGORY",self.zaurus.categories[entry['categories']]) # get an ical style repetition rule and add it rrule = datebook.zToICALFreq(entry) --- 105,109 ---- # only add the z plugin "category" field if it's not blank if( entry['categories'] ): ! vevent.addField("X-ZXSYNC-ZAURUS-CATEGORY",self.zaurus.categories[entry['categories']]) # get an ical style repetition rule and add it rrule = datebook.zToICALFreq(entry) *************** *** 113,117 **** vevent.addField("LOCATION", entry['location']) if( entry.has_key('rinfo') ): ! vevent.addField("X-ZAURUS-RINFO", entry['rinfo']) eventList.append(vevent) return eventList --- 113,117 ---- vevent.addField("LOCATION", entry['location']) if( entry.has_key('rinfo') ): ! vevent.addField("X-ZXSYNC-ZAURUS-RINFO", entry['rinfo']) eventList.append(vevent) return eventList |
From: <luc...@us...> - 2003-08-15 01:18:07
|
Update of /cvsroot/zxsync/zXSync/plugins/osx In directory sc8-pr-cvs1:/tmp/cvs-serv31025 Modified Files: ipodplugin.py Log Message: - support deleteField-notification - support changeField-notification Index: ipodplugin.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/osx/ipodplugin.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** ipodplugin.py 13 Jul 2003 08:55:19 -0000 1.6 --- ipodplugin.py 14 Aug 2003 20:07:24 -0000 1.7 *************** *** 212,215 **** --- 212,231 ---- + def notifyChangeField(self, newField, oldField): + """ + Called to notify the plugin when a field is about to be changed in + zXSync's internal pool of data for this application. + """ + return contacts.notifyChangeField(newField, oldField) + + + def notifyDeleteField(self, field, parentEntry): + """ + Called to notify the plugin when a field is about to be deleted in + zXSync's internal pool of data for this application. + """ + return contacts.notifyDeleteField(field, parentEntry) + + class iPodDevice(Device): """ |
From: <luc...@us...> - 2003-08-14 23:52:17
|
Update of /cvsroot/zxsync/zXSync/zxsync In directory sc8-pr-cvs1:/tmp/cvs-serv29740 Added Files: zapped.py Log Message: - added possibility to remove backups (useful if a device was re-initialized and should be re-synced completely) --- NEW FILE: zapped.py --- #!/usr/bin/env python # # zXSync helper in case a device was zapped. # # Copyright (C) 2003 Andreas Junghans <aj...@lu...> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # $Id: zapped.py,v 1.1 2003/08/14 19:59:11 lucidcake Exp $ # import sys import backup # command line interface if __name__ == "__main__": cmdError = 0 try: plugin = sys.argv[1] device = sys.argv[2] except: print "Usage: zapped <plugin> <device>" cmdError = 1 if not cmdError: backup.removeBackups(plugin, device) |
From: <luc...@us...> - 2003-08-14 23:50:54
|
Update of /cvsroot/zxsync/zXSync/plugins/osx In directory sc8-pr-cvs1:/tmp/cvs-serv31130 Modified Files: contacts.py Log Message: - support deleteField-notification - mark FN field as generated Index: contacts.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/osx/contacts.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** contacts.py 13 Jul 2003 08:53:18 -0000 1.6 --- contacts.py 14 Aug 2003 20:08:08 -0000 1.7 *************** *** 88,96 **** person.valueForProperty(addressbook.kABSuffixProperty) ) ! # special handling: since FN is just generated, set the field to ! # SYNC_TO to avoid conflicts fnField = personVCard.getChildWithId(vcard.FN) if fnField != None: ! fnField.setSyncMode(zxsync.syncbase.SYNC_TO) # NICKNAME field --- 88,95 ---- person.valueForProperty(addressbook.kABSuffixProperty) ) ! # special handling: mark FN as generated to avoid conflicts fnField = personVCard.getChildWithId(vcard.FN) if fnField != None: ! fnField.setGenerated(1) # NICKNAME field *************** *** 608,610 **** --- 607,620 ---- return 0 return 1 + + + def notifyDeleteField(field, parentEntry): + """ + Called to notify the plugin when a field is about to be deleted in + zXSync's internal pool of data for this application. + """ + fieldId = field.getId() + if not (fieldId in supportedFields): + return 0 + return 1 |
From: <luc...@us...> - 2003-08-14 23:28:20
|
Update of /cvsroot/zxsync/zXSync/zxsync In directory sc8-pr-cvs1:/tmp/cvs-serv30622 Modified Files: engine.py Log Message: - stop syncing an application if more than half of the entries on a device are deleted - support optional "--force-sync" argument to override the abovementioned behaviour - better argument parsing - minor bugfixes Index: engine.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/zxsync/engine.py,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** engine.py 13 Jul 2003 09:21:02 -0000 1.11 --- engine.py 14 Aug 2003 20:04:28 -0000 1.12 *************** *** 46,50 **** "PROBE_FAILED": "Probing plugin %1 for devices failed", "READ_ALL_FAILED": "Reading entries from a device provided by plugin %1 failed", ! "WRITE_FAILED": "Writing to a device provided by plugin %1 failed" } # for now --- 46,69 ---- "PROBE_FAILED": "Probing plugin %1 for devices failed", "READ_ALL_FAILED": "Reading entries from a device provided by plugin %1 failed", ! "WRITE_FAILED": "Writing to a device provided by plugin %1 failed", ! "TOO_MUCH_CHANGED": "\n\nAt least half of the entries of application '%3' on device '%2' " + ! "provided by plugin '%1' appear to " + ! "have been deleted and would normally be removed from other devices. " + ! "Perhaps this is just what you intended, but this would also be the case " + ! "if the device was re-inizialized or there was another severe failure. " + ! "\n\n" + ! "If you really want those entries to be removed, start zXSync again with " + ! "an additional --force-sync argument (but beware that this forces syncing " + ! "for all devices, so you better be sure that none of them - not just the " + ! "one reported in this message - was re-initialized " + ! "or otherwise failing!). If you want to keep the entries, use the " + ! "'zapped' utility of zXSync like this:" + ! "\n\n" + ! "python zxsync/zapped.py '%1' '%2'" + ! "\n\n" + ! "This command will rename the backup folder of the device so you can start " + ! "again with a clean state. Using 'zapped' is recommended since it doesn't " + ! "destroy information, while using --force-sync is possibly destructive " + ! "and should never be used under normal circumstances!\n\n" } # for now *************** *** 282,286 **** ! def beginSync(self, appToSync): """ Begins a a sync operation for the specified application. --- 301,305 ---- ! def beginSync(self, appToSync, forceSync): """ Begins a a sync operation for the specified application. *************** *** 345,355 **** if appToSyncFound: try: ! self.determineStatus(appToSync) self.setAutoSyncModes(appToSync) except: ! self.handleError(0, i18n["AUTO_SYNC_FAILED"], deviceInfo.plugin.__name__); ! def determineStatus(self, appToSync): """ Determines the sync modes according to the latest backups for the --- 364,374 ---- if appToSyncFound: try: ! self.determineStatus(appToSync, forceSync) self.setAutoSyncModes(appToSync) except: ! self.handleError(1, i18n["AUTO_SYNC_FAILED"], deviceInfo.plugin.__name__); ! def determineStatus(self, appToSync, forceSync): """ Determines the sync modes according to the latest backups for the *************** *** 385,388 **** --- 404,409 ---- else: continue + totalEntries = 0 + deletedEntries = 0 newVersion = deviceInfo.data for oldApp in oldVersion: *************** *** 397,400 **** --- 418,422 ---- continue for oldEntry in oldApp.getChildren(): + totalEntries += 1 #globalContext.log("Examining " + str(oldEntry) + " ...") matches = oldEntry.matchesInSequence(newApp.getChildren()) *************** *** 421,425 **** break if deleted: ! globalContext.log("Setting status to deleted: " + str(oldEntry)) temporaryEntry = oldEntry.deepClone() temporaryEntry.setStatus(syncbase.STATUS_DELETED) --- 443,448 ---- break if deleted: ! #globalContext.log("Setting status to deleted: " + str(oldEntry)) ! deletedEntries += 1 temporaryEntry = oldEntry.deepClone() temporaryEntry.setStatus(syncbase.STATUS_DELETED) *************** *** 441,445 **** if len(matches) == 0: #print "found", oldField ! globalContext.log("Setting status to deleted: " + str(oldField)) temporaryField = oldField.deepClone() temporaryField.setStatus(syncbase.STATUS_DELETED) --- 464,468 ---- if len(matches) == 0: #print "found", oldField ! #globalContext.log("Setting status to deleted: " + str(oldField)) temporaryField = oldField.deepClone() temporaryField.setStatus(syncbase.STATUS_DELETED) *************** *** 486,489 **** --- 509,517 ---- # for oldEntry in oldApp # for oldApp in oldVersion + if deletedEntries*2 >= totalEntries and not forceSync: + try: + raise SyncError + except: + self.handleError(1, i18n["TOO_MUCH_CHANGED"], deviceInfo.plugin.__name__, deviceInfo.device.getId(), appToSync) # for backup in backups.keys() *************** *** 665,669 **** elif child.allowsRemoving(): if matchingElement == None: ! remove = 1 elif len(child.matchesInSequence(matchingElement.getChildren())) == 0: remove = 1 --- 693,702 ---- elif child.allowsRemoving(): if matchingElement == None: ! #remove = 1 ! pass # removing in this case is not a good idea ! # (for example, if a field of a contact is ! # set to SYNC_TO and this contact is not ! # found on other devices, the field would be ! # deleted) elif len(child.matchesInSequence(matchingElement.getChildren())) == 0: remove = 1 *************** *** 1000,1003 **** --- 1033,1037 ---- cmdError = 0 dryRun = 0 + forceSync = 0 try: pluginsDir = sys.argv[1] *************** *** 1006,1013 **** #settings = {"osx.ipodplugin": [{"iPodName": "iPod"}]} if len(sys.argv) > 3: ! if sys.argv[3] == "--dry-run": ! dryRun = 1 except Exception, msg: ! print "Usage: engine <plugins dir> <settings> [--dry-run]" cmdError = 1 --- 1040,1052 ---- #settings = {"osx.ipodplugin": [{"iPodName": "iPod"}]} if len(sys.argv) > 3: ! for i in range(3, len(sys.argv)): ! if sys.argv[i] == "--dry-run": ! dryRun = 1 ! elif sys.argv[i] == "--force-sync": ! forceSync = 1 ! else: ! raise ValueError except Exception, msg: ! print "Usage: engine <plugins dir> <settings> [--dry-run] [--force-sync]" cmdError = 1 *************** *** 1019,1031 **** # circumvented by a wrapper shell script that changes to this dir. engine = SyncEngine() engine.findPlugins(pluginsDir) engine.findDevices(settings) ! engine.beginSync(syncbase.CALENDAR_APP_ID) ! engine.syncData(dryRun, syncbase.CALENDAR_APP_ID) ! engine.endSync(syncbase.CALENDAR_APP_ID) ! engine.beginSync(syncbase.CONTACTS_APP_ID) ! engine.syncData(dryRun, syncbase.CONTACTS_APP_ID) ! engine.endSync(syncbase.CONTACTS_APP_ID) print report.createReport(engine.devices, engine.conflictList, dryRun) --- 1058,1082 ---- # circumvented by a wrapper shell script that changes to this dir. + syncError = 0 engine = SyncEngine() engine.findPlugins(pluginsDir) engine.findDevices(settings) ! try: ! engine.beginSync(syncbase.CALENDAR_APP_ID, forceSync) ! engine.syncData(dryRun, syncbase.CALENDAR_APP_ID) ! except: ! engine.cancelSync() ! syncError = 1 ! if not syncError: ! engine.endSync(syncbase.CALENDAR_APP_ID) ! syncError = 0 ! try: ! engine.beginSync(syncbase.CONTACTS_APP_ID, forceSync) ! engine.syncData(dryRun, syncbase.CONTACTS_APP_ID) ! except: ! engine.cancelSync() ! syncError = 1 ! if not syncError: ! engine.endSync(syncbase.CONTACTS_APP_ID) print report.createReport(engine.devices, engine.conflictList, dryRun) |
From: <luc...@us...> - 2003-08-14 23:03:16
|
Update of /cvsroot/zxsync/zXSync/zxsync In directory sc8-pr-cvs1:/tmp/cvs-serv29654 Modified Files: backup.py Log Message: - added possibility to remove backups (useful if a device was re-initialized and should be re-synced completely) Index: backup.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/zxsync/backup.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** backup.py 13 Jul 2003 09:04:15 -0000 1.1 --- backup.py 14 Aug 2003 19:58:35 -0000 1.2 *************** *** 35,38 **** --- 35,39 ---- import sys import time + import shutil *************** *** 170,173 **** --- 171,194 ---- + def removeBackups(pluginId, deviceId): + """ + Removes all backups of the specified plugin and device. In fact, the + backups are not really removed, only the backup folder is renamed + (however, if a previously renamed folder exists, it is deleted so that + the renaming can take place). + + The purpose of this is to throw away backups that won't be used anymore. + For example, if a device is re-initialized, all entries that were + previously on it would be marked for deletion on the other devices + (zXSync doesn't know they were not removed intentionally). By removing + the old backups before the sync, this situtation can be avoided. + """ + devicePath = os.path.join(basePath, pluginId, deviceId) + backupPath = os.path.join(basePath, pluginId, deviceId + ".zxsync_bak") + if os.path.exists(backupPath): + shutil.rmtree(backupPath) + os.rename(devicePath, backupPath) + + def loadBackup(pluginId, deviceId, appId, postSync): """ |
From: <luc...@us...> - 2003-08-14 22:00:36
|
Update of /cvsroot/zxsync/zXSync/plugins/osx In directory sc8-pr-cvs1:/tmp/cvs-serv30931 Modified Files: osxplugin.py Log Message: - support deleteField-notification Index: osxplugin.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/osx/osxplugin.py,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** osxplugin.py 13 Jul 2003 08:57:38 -0000 1.9 --- osxplugin.py 14 Aug 2003 20:06:52 -0000 1.10 *************** *** 158,161 **** --- 158,169 ---- return contacts.notifyChangeField(newField, oldField) + + def notifyDeleteField(self, field, parentEntry): + """ + Called to notify the plugin when a field is about to be deleted in + zXSync's internal pool of data for this application. + """ + return contacts.notifyDeleteField(field, parentEntry) + class OSXDevice(Device): |
From: <luc...@us...> - 2003-08-14 20:22:18
|
Update of /cvsroot/zxsync/zXSync/zxsync In directory sc8-pr-cvs1:/tmp/cvs-serv30061 Modified Files: syncbase.py vcard.py Log Message: - supported marking a field as "generated" (so it can be treated as non-conflicting) Index: syncbase.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/zxsync/syncbase.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** syncbase.py 13 Jul 2003 09:13:01 -0000 1.6 --- syncbase.py 14 Aug 2003 20:00:44 -0000 1.7 *************** *** 685,688 **** --- 685,689 ---- HierarchyElement.__init__(self, id) self.value = value + self.generated = 0 *************** *** 710,713 **** --- 711,731 ---- + def setGenerated(self, generated): + """ + Marks this field as generated or not (with not generated being the + default). This information can be used in subclasses to determine if + there's a conflict with another field (since generated fields should + generally not be considered conflicting with anything). + """ + self.generated = generated + + + def isGenerated(self): + """ + Returns whether this field is marked as generated. + """ + return self.generated + + def conflictsWith(self, field): """ Index: vcard.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/zxsync/vcard.py,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** vcard.py 13 Jul 2003 09:08:17 -0000 1.8 --- vcard.py 14 Aug 2003 20:00:44 -0000 1.9 *************** *** 443,450 **** def doesConflictWith(self, other): ! if self.getValue() == other.getValue(): #or self.getId() == UID: ! # UIDs never conflict ! # (now obsolete since UIDs are no longer treated as ordinary ! # fields) return 0 return 1 --- 443,448 ---- def doesConflictWith(self, other): ! if self.getValue() == other.getValue() or self.isGenerated(): ! # generated fields never conflict return 0 return 1 |
From: <luc...@us...> - 2003-07-13 09:21:05
|
Update of /cvsroot/zxsync/zXSync/zxsync In directory sc8-pr-cvs1:/tmp/cvs-serv31011 Modified Files: engine.py Log Message: - Added automatic backups - Added automatic sync mode assignment based on the backups - Added (very simple) logging via the context - Output a lot of log messages to better track the progress while syncing - A lot of bug fixes for dry-runs - Skip a lot of sync stuff if an application cannot be found on a device (improves performance and necessary for backups) - Various small bug fixes Index: engine.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/zxsync/engine.py,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** engine.py 23 Jun 2003 21:10:52 -0000 1.10 --- engine.py 13 Jul 2003 09:21:02 -0000 1.11 *************** *** 27,33 **** --- 27,35 ---- import vcard import report + import backup i18n = { + "AUTO_SYNC_FAILED": "Automatic sync mode assignment for a device provided by plugin %1 failed", "BEGIN_SYNC_FAILED": "Beginning sync for a device provided by plugin %1 failed", "END_SYNC_FAILED": "Ending sync for a device provided by plugin %1 failed", *************** *** 41,44 **** --- 43,47 ---- "INIT_DEVICE_FAILED": "Initializing a device provided by plugin %1 failed", "LOADING_PLUGIN_FAILED": "Loading plugin %1 failed", + "POST_SYNC_BACKUP_FAILED": "Creating backups after syncing failed", "PROBE_FAILED": "Probing plugin %1 for devices failed", "READ_ALL_FAILED": "Reading entries from a device provided by plugin %1 failed", *************** *** 107,110 **** --- 110,121 ---- raise + + def log(self, message): + """ + Logs a message. This implementation simply prints the message to the console. + """ + print "[zXSync]", message + + globalContext = SyncContext() *************** *** 149,155 **** self.removeRejectedList = [] # removals vetoed by the device self.changeRejectedList = [] # changes rejected by the device - self.addListBackup = [] - self.removeListBackup = [] - self.changeListBackup = [] self.apps = [] # set to an empty list in case the next call raises an exception --- 160,163 ---- *************** *** 251,254 **** --- 259,263 ---- pass try: + globalContext.log("Probing '" + plugin.__name__ + "' ...") moduleDevices = plugin.__dict__["probe"](pluginSettings, globalContext) except: *************** *** 277,280 **** --- 286,290 ---- Begins a a sync operation for the specified application. """ + appToSyncFound = 0 for deviceInfo in self.devices: device = deviceInfo.device *************** *** 289,292 **** --- 299,303 ---- deviceApp = appInfo.app if deviceApp.getId() == appToSync: + appToSyncFound = 1 if appInfo.syncStarted: appInfo.syncStarted = 0 *************** *** 296,299 **** --- 307,313 ---- self.handleError(0, i18n["END_SYNC_FAILED"], deviceInfo.plugin.__name__); try: + globalContext.log("Calling beginSync() for '" + + deviceInfo.plugin.__name__ + "/" + + device.getId() + "' ...") writeMode = deviceApp.beginSync() appInfo.syncStarted = 1 *************** *** 304,312 **** globalContext.fatalDefault = READ_ERRORS_ARE_FATAL try: deviceEntries = deviceApp.readAllEntries() removeList = [] for deviceEntry in deviceEntries: if not deviceEntry.isValid(): ! print "Invalid entry:", deviceEntry removeList.append(deviceEntry) for removeEntry in removeList: --- 318,329 ---- globalContext.fatalDefault = READ_ERRORS_ARE_FATAL try: + globalContext.log("Calling readAllEntries() for '" + + deviceInfo.plugin.__name__ + "/" + + device.getId() + "' ...") deviceEntries = deviceApp.readAllEntries() removeList = [] for deviceEntry in deviceEntries: if not deviceEntry.isValid(): ! globalContext.log("Invalid entry: " + str(deviceEntry)) removeList.append(deviceEntry) for removeEntry in removeList: *************** *** 319,322 **** --- 336,340 ---- deviceInfo.data.append(newApp) deviceInfo.entriesRead += len(deviceEntries) + globalContext.fatalDefault = oldFatalDefault except: globalContext.fatalDefault = oldFatalDefault *************** *** 325,329 **** # (2) the plugin called handleError() with fatal == true # or (3) the default for read errors is fatal ! globalContext.fatalDefault = oldFatalDefault --- 343,543 ---- # (2) the plugin called handleError() with fatal == true # or (3) the default for read errors is fatal ! if appToSyncFound: ! try: ! self.determineStatus(appToSync) ! self.setAutoSyncModes(appToSync) ! except: ! self.handleError(0, i18n["AUTO_SYNC_FAILED"], deviceInfo.plugin.__name__); ! ! ! def determineStatus(self, appToSync): ! """ ! Determines the sync modes according to the latest backups for the ! specified app. ! ! Note that entries and fields that have been added since the last ! backup will have a status of STATUS_UNKNOWN instead of STATUS_ADDED. ! This is OK since the default sync mode of SYNC_BOTH will still get ! them distributed. Probably STATUS_ADDED will be removed altogether ! some day (since it's additinal unnecessary work to find out what has ! been addded and assign that status). ! """ ! backups = backup.loadBackups(self.devices, appToSync, 1) ! # "1" means load post-sync backups ! if len(backups) > 0: ! globalContext.log("Using previous '" + appToSync + ! "' backups to automatically assign sync modes ...") ! else: ! globalContext.log("No previous '" + appToSync + ! "' backups found - no sync modes will be assigned automatically") ! ! # determine the status of all entries and fields ! temporaries = [] ! #print backups.keys() ! for backupKey in backups.keys(): ! oldVersion = backups[backupKey] ! for deviceInfo in self.devices: ! if deviceInfo.plugin.__name__ == backupKey[0] and \ ! deviceInfo.device.getId() == backupKey[1]: ! #print "found", backupKey ! globalContext.log("Examining " + str(backupKey) + " ...") ! break ! else: ! continue ! newVersion = deviceInfo.data ! for oldApp in oldVersion: ! if oldApp.getId() != appToSync: ! continue ! for newApp in newVersion: ! if newApp.getId() == oldApp.getId(): ! #print "found", newApp.getId(); ! globalContext.log("Examining " + str(newApp.getId()) + " ...") ! break ! else: ! continue ! for oldEntry in oldApp.getChildren(): ! #globalContext.log("Examining " + str(oldEntry) + " ...") ! matches = oldEntry.matchesInSequence(newApp.getChildren()) ! if len(matches) > 1: ! # not much we can do ! continue ! elif len(matches) == 1: ! # examine the entry anyway, regardless of ids ! # (which might be bogus) ! newEntry = matches[0] ! else: ! deleted = 1 ! for newEntry in newApp.getChildren(): ! if oldEntry.getId() == newEntry.getId(): ! # we have no match but equal ids: ! # check if key fields (involved in matching) ! # have changed ! matches = newEntry.matchesInSequence(oldApp.getChildren()) ! if len(matches) == 0: ! # we have no match in either direction, ! # but ids are equal -> assume key fields ! # have changed ! deleted = 0 ! break ! if deleted: ! globalContext.log("Setting status to deleted: " + str(oldEntry)) ! temporaryEntry = oldEntry.deepClone() ! temporaryEntry.setStatus(syncbase.STATUS_DELETED) ! temporaryEntry.setParent(newApp) ! temporaries.append(temporaryEntry) ! continue ! # if we're here, we either have a matching entry or two ! # entries with equal ids (and no match at all) ! if oldEntry.isValid(): ! newEntry.setPreviousEntry(oldEntry) ! # The validity check is necessary because the ! # isValid() implementation might have changed after ! # the backup was made. Since the previous entry is ! # used for matching, it is essential that it is ! # valid. ! changed = 0 ! for oldField in oldEntry.getChildren(): ! matches = oldField.matchesInSequence(newEntry.getChildren()) ! if len(matches) == 0: ! #print "found", oldField ! globalContext.log("Setting status to deleted: " + str(oldField)) ! temporaryField = oldField.deepClone() ! temporaryField.setStatus(syncbase.STATUS_DELETED) ! temporaryField.setParent(newEntry) ! temporaries.append(temporaryField) ! changed = 1 ! elif len(matches) == 1: ! newField = matches[0] ! if not oldField.equals(newField): ! #print "found", oldField ! globalContext.log("Setting status to changed: " + str(oldField) + " to " + str(newField)) ! newField.setStatus(syncbase.STATUS_CHANGED) ! changed = 1 ! else: ! newField.setStatus(syncbase.STATUS_UNCHANGED) ! else: ! for newField in matches: ! if not oldField.equals(newField): ! globalContext.log("Strange match for '" + ! deviceInfo.plugin.__name__ + "/" + ! deviceInfo.device.getId() + "/" + ! oldApp.getId() + "/" + ! oldField.getId() + "'!"); ! # this shouldn't normally happen ! # since the only case where we have ! # several matches here should be when ! # the exact same field is present ! # more than once ! globalContext.log("Setting status to changed") ! newField.setStatus(syncbase.STATUS_CHANGED) ! changed = 1 ! else: ! pass ! # leave the status as STATUS_UNKNOWN since ! # this might be a newly added duplicate ! # (and there's no sense flagging that as ! # UNCHANGED) ! if changed: ! newEntry.setStatus(syncbase.STATUS_CHANGED, 0) ! else: ! pass ! # leave the status as STATUS_UNKNOWN since we don't ! # currently check for added entries ! # for oldEntry in oldApp ! # for oldApp in oldVersion ! # for backup in backups.keys() ! ! for temporary in temporaries: ! temporary.getParent().addChild(temporary) ! ! ! def setAutoSyncModes(self, appToSync): ! """ ! Automatically sets sync modes according to the status of each ! entry/field. ! """ ! ! temporaries = [] ! #print len(self.devices), "devices present" ! for deviceInfo in self.devices: ! for app in deviceInfo.data: ! if app.getId() != appToSync: ! continue ! matchingApps = [] ! for checkDeviceInfo in self.devices: ! for checkApp in checkDeviceInfo.data: ! if checkApp.getId() == appToSync: ! matchingApps.append(checkApp) ! for entry in app.getChildren(): ! status = entry.getStatus() ! if status == syncbase.STATUS_DELETED: ! matchingEntries = entry.matchesInParentSequence(matchingApps) ! for matchingEntry in matchingEntries: ! matchingEntryStatus = matchingEntry.getStatus() ! if matchingEntryStatus == syncbase.STATUS_UNKNOWN or \ ! matchingEntryStatus == syncbase.STATUS_UNCHANGED: ! matchingEntry.setSyncMode(syncbase.SYNC_TO) ! temporaries.append(entry) ! elif status == syncbase.STATUS_CHANGED: ! matchingEntries = entry.matchesInParentSequence(matchingApps) ! #print "changed entry found with", len(matchingEntries), "matching entries" ! for field in entry.getChildren(): ! status = field.getStatus() ! if status == syncbase.STATUS_DELETED or \ ! status == syncbase.STATUS_CHANGED: ! matchingFields = field.matchesInParentSequence(matchingEntries) ! #print len(matchingFields), "matching fields found" ! for matchingField in matchingFields: ! matchingFieldStatus = matchingField.getStatus() ! #print "status:", matchingFieldStatus ! if matchingFieldStatus == syncbase.STATUS_UNKNOWN or \ ! matchingFieldStatus == syncbase.STATUS_UNCHANGED: ! #print "setting field mode to SYNC_TO" ! matchingField.setSyncMode(syncbase.SYNC_TO) ! if status == syncbase.STATUS_DELETED: ! temporaries.append(field) ! ! for temporary in temporaries: ! temporary.getParent().removeChild(temporary) *************** *** 427,430 **** --- 641,645 ---- # information ...) deviceInfo.changeList.append(newElement) + #print "check:", newElement.getParent().isLeaf() else: # check if we have to add data *************** *** 466,469 **** --- 681,685 ---- while information to that entry has been added on two other devices. """ + appFound = 0 self.aggregatedData = syncbase.HierarchyElement() self.conflictList = [] *************** *** 471,474 **** --- 687,695 ---- for syncApp in deviceInfo.data: if syncApp.getId() == appToSync: + appFound = 1 + globalContext.log("Aggregating data from '" + + deviceInfo.plugin.__name__ + "/" + + deviceInfo.device.getId() + "/" + + appToSync + "' into the global pool ...") # if reading is not allowed, back out here if not syncApp.allowsReading(): *************** *** 476,479 **** --- 697,701 ---- self.doAggregateData(syncApp, self.aggregatedData, self.findMatchingApps(syncApp)) + return appFound *************** *** 486,489 **** --- 708,715 ---- for syncApp in deviceInfo.data: if syncApp.getId() == appToSync: + globalContext.log("Distributing changes to '" + + deviceInfo.plugin.__name__ + "/" + + deviceInfo.device.getId() + "/" + + appToSync + "' ...") self.doDistributeData(deviceInfo, syncApp, syncApp.matchesInSequence(self.aggregatedData.getChildren())) *************** *** 492,498 **** def saveInternalData(self): """ ! Clones all internal data and the add/remove/change lists of the ! devices. Then, the clones are put into the place of the originals ! which are stored in backup attributes. """ for deviceInfo in self.devices: --- 718,725 ---- def saveInternalData(self): """ ! Clones all internal data. Then, the clones are put into the place of ! the originals which are stored in a backup. ! ! TODO: restrict this to the current app that is synced """ for deviceInfo in self.devices: *************** *** 502,526 **** deviceInfo.dataBackup = deviceInfo.data deviceInfo.data = newData - newAddList = [] for element in deviceInfo.addList: ! newElement = element.deepClone() ! newElement.parent = element.getParent().getClone() ! newAddList.append(newElement) ! deviceInfo.addListBackup = deviceInfo.addList ! deviceInfo.addList = newAddList ! newChangeList = [] for element in deviceInfo.changeList: ! newElement = element.deepClone() ! newElement.parent = element.getParent().getClone() ! newChangeList.append(newElement) ! deviceInfo.changeListBackup = deviceInfo.changeList ! deviceInfo.changeList = newChangeList ! newRemoveList = [] ! for element in deviceInfo.removeList: ! newElement = element.deepClone() ! newElement.parent = element.getParent().getClone() ! newRemoveList.append(newElement) ! deviceInfo.removeListBackup = deviceInfo.removeList ! deviceInfo.removeList = newRemoveList --- 729,744 ---- deviceInfo.dataBackup = deviceInfo.data deviceInfo.data = newData for element in deviceInfo.addList: ! element.parent = element.getParent().getClone() for element in deviceInfo.changeList: ! #print "check 2:", element.getParent().isLeaf() ! element.parent = element.getParent().getClone() ! #print "check 3:", element.getParent().isLeaf() ! # special handling for remove list: ! # the removed entries are the exact same ones ! # present in their parents (and this property must be ! # preserved for the remove the work) ! for index in range(len(deviceInfo.removeList)): ! deviceInfo.removeList[index] = deviceInfo.removeList[index].getClone() *************** *** 530,545 **** the same time, the rejected lists are changed so that they point to the original data instead of the cloned version. """ for deviceInfo in self.devices: deviceInfo.data = deviceInfo.dataBackup ! deviceInfo.addList = deviceInfo.addListBackup ! deviceInfo.changeList = deviceInfo.changeListBackup ! deviceInfo.removeList = deviceInfo.removeListBackup for element in deviceInfo.addRejectedList: element.parent = element.getParent().getOriginal() for element in deviceInfo.changeRejectedList: element.parent = element.getParent().getOriginal() ! for element in deviceInfo.removeRejectedList: ! element.parent = element.getParent().getOriginal() --- 748,770 ---- the same time, the rejected lists are changed so that they point to the original data instead of the cloned version. + + TODO: restrict this to the current app that is synced """ for deviceInfo in self.devices: deviceInfo.data = deviceInfo.dataBackup ! for element in deviceInfo.addList: ! element.parent = element.getParent().getOriginal() ! for element in deviceInfo.changeList: ! #print "check 4:", element.getParent().isLeaf() ! element.parent = element.getParent().getOriginal() ! #print "check 5:", element.getParent().isLeaf() ! for index in range(len(deviceInfo.removeList)): ! deviceInfo.removeList[index] = deviceInfo.removeList[index].getOriginal() for element in deviceInfo.addRejectedList: element.parent = element.getParent().getOriginal() for element in deviceInfo.changeRejectedList: element.parent = element.getParent().getOriginal() ! for index in range(len(deviceInfo.removeRejectedList)): ! deviceInfo.removeRejectedList[index] = deviceInfo.removeRejectedList[index].getOriginal() *************** *** 550,568 **** """ ! self.aggregateData(appToSync) # aggregates the data from all devices and checks for conflicts if len(self.conflictList) > 0: return self.distributeData(appToSync) ! # adds, changes, and deletes entries - # backup the data so changes do not really take effect # (however, they have to be made anyway or we won't get # sensible rejected lists) ! #if checkConflictsOnly: ! # self.saveInternalData() # change the (maybe saved before) internal data --- 775,798 ---- """ ! appFound = self.aggregateData(appToSync) # aggregates the data from all devices and checks for conflicts if len(self.conflictList) > 0: + globalContext.log("Conflicts found!") + return + if not appFound: return self.distributeData(appToSync) ! # builds add, change, and remove lists # backup the data so changes do not really take effect # (however, they have to be made anyway or we won't get # sensible rejected lists) ! if checkConflictsOnly: ! self.saveInternalData() ! else: ! # make a pre-sync backup ! backup.createBackups(self.devices, appToSync, 0) # change the (maybe saved before) internal data *************** *** 572,575 **** --- 802,814 ---- for deviceInfo in self.devices: + if checkConflictsOnly: + globalContext.log("Simulating writing data to '" + + deviceInfo.plugin.__name__ + "/" + + deviceInfo.device.getId() + "' ...") + else: + globalContext.log("Writing data to '" + + deviceInfo.plugin.__name__ + "/" + + deviceInfo.device.getId() + "' ...") + # actually put the info into the data tree (necessary for # WRITE_ALL mode) and additionally translate everything *************** *** 584,591 **** parent = element.getParent() if element.isLeaf(): ! retVal = parent.getParent.getSource().nofityRemoveField( element, parent) if retVal: parent.removeChild(element) if not (parent in changedEntries): changedEntries.append(parent) --- 823,832 ---- parent = element.getParent() if element.isLeaf(): ! retVal = parent.getParent().getSource().notifyDeleteField( element, parent) if retVal: parent.removeChild(element) + element.parent = parent + # restore parent (has been set to None by removeChild()) if not (parent in changedEntries): changedEntries.append(parent) *************** *** 597,601 **** # this must be an entry since whole applications # are never removed and fields are leafs ! retVal = parent.getSource().notifyRemoveEntry( element, parent) if retVal: --- 838,842 ---- # this must be an entry since whole applications # are never removed and fields are leafs ! retVal = parent.getSource().notifyDeleteEntry( element, parent) if retVal: *************** *** 611,615 **** while index < len(deviceInfo.changeList): # changed elements must be fields ! element = deviceInfo.changeList[index] oldElement = element.getParent() parent = oldElement.getParent() --- 852,859 ---- while index < len(deviceInfo.changeList): # changed elements must be fields ! temp = deviceInfo.changeList[index] ! element = temp.deepClone() ! # clone in order to preserve the element in the list exactly ! element.parent = temp.getParent() oldElement = element.getParent() parent = oldElement.getParent() *************** *** 629,633 **** index = 0 while index < len(deviceInfo.addList): ! element = deviceInfo.addList[index] parent = element.getParent() if element.isLeaf(): --- 873,880 ---- index = 0 while index < len(deviceInfo.addList): ! temp = deviceInfo.addList[index] ! element = temp.deepClone() ! # clone in order to preserve the element in the list exactly ! element.parent = temp.getParent() parent = element.getParent() if element.isLeaf(): *************** *** 659,663 **** if not checkConflictsOnly: for syncApp in deviceInfo.data: ! if syncApp.getSource().getId() == appToSync: if syncApp.getWriteMode() == syncbase.WRITE_SINGLE: for entry in addedEntries: --- 906,910 ---- if not checkConflictsOnly: for syncApp in deviceInfo.data: ! if syncApp.getId() == appToSync: if syncApp.getWriteMode() == syncbase.WRITE_SINGLE: for entry in addedEntries: *************** *** 669,673 **** --- 916,958 ---- else: syncApp.getSource().writeAllEntries(syncApp.getChildren()) + + # if this was no dry-run, make post-sync backups + if not checkConflictsOnly: + try: + # we have to re-read everything since what we tell + # a plugin to write is not necessarily what it actually + # writes ... + for deviceInfo in self.devices: + for app in deviceInfo.data: + if app.getId() == appToSync: + deviceApp = app.getSource() + deviceEntries = deviceApp.readAllEntries() + removeList = [] + for deviceEntry in deviceEntries: + if not deviceEntry.isValid(): + globalContext.log("Invalid entry: " + str(deviceEntry)) + removeList.append(deviceEntry) + for removeEntry in removeList: + deviceEntries.remove(removeEntry) + newApp = syncbase.Application(deviceApp.getId()) + newApp.setSource(deviceApp) + newApp.setDeviceInfo(deviceInfo) + newApp.addChildren(deviceEntries) + backup.createBackup(deviceInfo.plugin.__name__, + deviceInfo.device.getId(), + newApp, 1) + except: + self.handleError(0, i18n["POST_SYNC_BACKUP_FAILED"]); + # not considered fatal + # TODO: better error message (e.g. which device failed) + + # if this was only a dry-run, restore the internal data + if checkConflictsOnly: + self.restoreInternalData() + globalContext.fatalDefault = oldFatalDefault + except: + if checkConflictsOnly: + self.restoreInternalData() globalContext.fatalDefault = oldFatalDefault self.handleError(1, i18n["WRITE_FAILED"], deviceInfo.plugin.__name__); *************** *** 675,686 **** # (2) the plugin called handleError() with fatal == true # or (3) the default for write errors is fatal ! ! globalContext.fatalDefault = oldFatalDefault ! ! # if this was only a conflict check, revert the internal data to ! # the saved state ! #if checkConflictsOnly: ! # self.restoreInternalData() ! def cancelSync(self): --- 960,966 ---- # (2) the plugin called handleError() with fatal == true # or (3) the default for write errors is fatal ! # note: handleError might throw an exception ! ! def cancelSync(self): |
From: <luc...@us...> - 2003-07-13 09:13:08
|
Update of /cvsroot/zxsync/zXSync/zxsync In directory sc8-pr-cvs1:/tmp/cvs-serv30314 Modified Files: syncbase.py Log Message: - Added automatic sync mode assignment based on the backups - Bug fixes for cloning (some attributes were not copied) Index: syncbase.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/zxsync/syncbase.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** syncbase.py 23 Jun 2003 21:16:29 -0000 1.5 --- syncbase.py 13 Jul 2003 09:13:01 -0000 1.6 *************** *** 29,32 **** --- 29,38 ---- SYNC_DELETE = 4 + STATUS_UNKNOWN = 0 + STATUS_UNCHANGED = 1 + STATUS_CHANGED = 2 + STATUS_ADDED = 3 + STATUS_DELETED = 4 + WRITE_SINGLE = 1 # the plugin wants to write single entries WRITE_ALL = 2 # the plugin wants to write all entries at once *************** *** 56,59 **** --- 62,66 ---- """ self.syncMode = SYNC_BOTH + self.status = STATUS_UNKNOWN self.children = [] self.parent = None *************** *** 77,80 **** --- 84,88 ---- """ other.syncMode = self.syncMode + other.status = self.status other.parent = None other.id = self.id *************** *** 308,311 **** --- 316,337 ---- + def getStatus(self): + """ + Returns the status of this element. + """ + return self.status + + + def setStatus(self, status, modifyChildren = 1): + """ + Sets the status of this element. If "modifyChildren" is true, the + children of this element is also modified. + """ + if modifyChildren: + for child in self.children: + child.setStatus(status, 1) + self.status = status + + def getChildren(self): """ *************** *** 469,472 **** --- 495,511 ---- + def __getstate__(self): + retVal = self.__dict__.copy() + del retVal["clonedElement"] + del retVal["originalElement"] + return retVal + + + def __setstate__(self, state): + self.__dict__.update(state) + self.clonedElement = None + self.originalElement = None + + def __repr__(self): return repr(self.children) *************** *** 482,485 **** --- 521,542 ---- """ + def __init__(self, id = None): + """ + Initializes the application. + """ + self.source = None + self.deviceInfo = None + HierarchyElement.__init__(self, id) + + + def doClone(self, other): + """ + Internal clone implementation for this class. + """ + other.source = self.source + other.deviceInfo = self.deviceInfo + return HierarchyElement.doClone(self, other) + + def clone(self): """ *************** *** 536,539 **** --- 593,609 ---- + def __getstate__(self): + retVal = HierarchyElement.__getstate__(self) + del retVal["source"] + del retVal["deviceInfo"] + return retVal + + + def __setstate__(self, state): + HierarchyElement.__setstate__(self, state) + self.source = None + self.deviceInfo = None + + class Entry(HierarchyElement): """ *************** *** 541,544 **** --- 611,630 ---- """ + def __init__(self, id = None): + """ + Initializes the application. + """ + self.previousEntry = None + HierarchyElement.__init__(self, id) + + + def doClone(self, other): + """ + Internal clone implementation for this class. + """ + other.previousEntry = self.previousEntry + return HierarchyElement.doClone(self, other) + + def clone(self): """ *************** *** 547,550 **** --- 633,664 ---- return self.doClone(Entry()) + + def setPreviousEntry(self, previousEntry): + """ + Sets the previous version of this entry (loaded from a backup). + """ + self.previousEntry = previousEntry + + + def getPreviousEntry(self): + """ + Returns the previous version of this entry (loaded from a backup). + This can (and should!) be used for matching if it's not None. This + way, changes to fields that influence the matching process are + handled correctly. + """ + return self.previousEntry + + + def __getstate__(self): + retVal = HierarchyElement.__getstate__(self) + del retVal["previousEntry"] + return retVal + + + def __setstate__(self, state): + HierarchyElement.__setstate__(self, state) + self.previousEntry = None + class Field(HierarchyElement): |
From: <luc...@us...> - 2003-07-13 09:10:47
|
Update of /cvsroot/zxsync/zXSync/zxsync In directory sc8-pr-cvs1:/tmp/cvs-serv30083 Modified Files: pluginbase.py Log Message: - Added the notion of device ids (necessary for backups) - Support passing the parent in delete notifications (makes life easier for plugins) Index: pluginbase.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/zxsync/pluginbase.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** pluginbase.py 23 Jun 2003 21:14:17 -0000 1.5 --- pluginbase.py 13 Jul 2003 09:10:44 -0000 1.6 *************** *** 32,35 **** --- 32,36 ---- pass + class Device: """ *************** *** 49,52 **** --- 50,63 ---- + def getId(self): + """ + Returns the id of the device (necessary for backup and status + support). + + This id must be unique per plugin. + """ + raise PluginError("Device.getId() not implemented.") + + def init(self, context): """Perform any one-time initializations required by the plugin""" *************** *** 198,202 **** ! def notifyDeleteField(self, field): """ Called to notify the plugin when a field is about to be deleted from --- 209,213 ---- ! def notifyDeleteField(self, field, parentEntry): """ Called to notify the plugin when a field is about to be deleted from *************** *** 229,233 **** ! def notifyDeleteEntry(self, entry): """ Called to notify the plugin when an entry is about to be deleted from --- 240,244 ---- ! def notifyDeleteEntry(self, entry, parentApp): """ Called to notify the plugin when an entry is about to be deleted from |
From: <luc...@us...> - 2003-07-13 09:08:20
|
Update of /cvsroot/zxsync/zXSync/zxsync In directory sc8-pr-cvs1:/tmp/cvs-serv29829 Modified Files: vcard.py Log Message: - Removed UID field from vCards (the id is still available via getId(), but not as a field). This avoids a lot of trouble when the ids of a plugin are not worth much (as is currently the case with iPod and Zaurus contacts ;-)) - Added automatic sync mode assignment based on the backups (in case of vCards, use the previous field values for matching, not the current ones) Index: vcard.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/zxsync/vcard.py,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** vcard.py 23 Jun 2003 21:21:02 -0000 1.7 --- vcard.py 13 Jul 2003 09:08:17 -0000 1.8 *************** *** 29,34 **** ! UID = "UID" ! UID_DEFAULT = "" FN = "FN" FN_DEFAULT = "" --- 29,35 ---- ! #UID = "UID" ! #UID_DEFAULT = "" ! # don't treat the UID as an ordinary field FN = "FN" FN_DEFAULT = "" *************** *** 442,447 **** def doesConflictWith(self, other): ! if self.getValue() == other.getValue() or self.getId() == UID: # UIDs never conflict return 0 return 1 --- 443,450 ---- def doesConflictWith(self, other): ! if self.getValue() == other.getValue(): #or self.getId() == UID: # UIDs never conflict + # (now obsolete since UIDs are no longer treated as ordinary + # fields) return 0 return 1 *************** *** 482,486 **** """ Entry.__init__(self, id) ! self.replaceOrRemoveChild(UID, UID_DEFAULT, convertToInternalValue(id)) --- 485,491 ---- """ Entry.__init__(self, id) ! #self.replaceOrRemoveChild(UID, UID_DEFAULT, convertToInternalValue(id)) ! # don't treat the UID as an ordinary field (that just creates some ! # ugly problems when syncing *************** *** 538,544 **** """ # TODO: add matching via UID match table ! selfName = self.getName() if selfName != None: ! otherName = other.getName() if otherName == None: return 0 --- 543,555 ---- """ # TODO: add matching via UID match table ! matchSelf = self.getPreviousEntry() ! if matchSelf == None: ! matchSelf = self ! matchOther = other.getPreviousEntry() ! if matchOther == None: ! matchOther = other ! selfName = matchSelf.getName() if selfName != None: ! otherName = matchOther.getName() if otherName == None: return 0 *************** *** 547,553 **** return 1 ! selfMails = self.getEmailAddresses() if len(selfMails) > 0: ! otherMails = other.getEmailAddresses() if len(selfMails) != len(otherMails): return 0 --- 558,564 ---- return 1 ! selfMails = matchSelf.getEmailAddresses() if len(selfMails) > 0: ! otherMails = matchOther.getEmailAddresses() if len(selfMails) != len(otherMails): return 0 *************** *** 562,570 **** return 1 ! selfOrgs = self.getOrganizations() assert len(selfOrgs) > 0 # if this is not the case, a plugin has an incorrect # implementation of isValid() ! otherOrgs = other.getOrganizations() if len(selfOrgs) != len(otherOrgs): return 0 --- 573,581 ---- return 1 ! selfOrgs = matchSelf.getOrganizations() assert len(selfOrgs) > 0 # if this is not the case, a plugin has an incorrect # implementation of isValid() ! otherOrgs = matchOther.getOrganizations() if len(selfOrgs) != len(otherOrgs): return 0 *************** *** 590,598 **** ! def getUID(self): ! """ ! Returns the UID field of this vCard as a VCardField. ! """ ! return self.getChildWithId(UID) --- 601,609 ---- ! #def getUID(self): ! # """ ! # Returns the UID field of this vCard as a VCardField. ! # """ ! # return self.getChildWithId(UID) |
From: <luc...@us...> - 2003-07-13 09:05:06
|
Update of /cvsroot/zxsync/zXSync/zxsync In directory sc8-pr-cvs1:/tmp/cvs-serv29529 Modified Files: report.py Log Message: - Added warning comment Index: report.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/zxsync/report.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** report.py 23 Jun 2003 21:11:56 -0000 1.1 --- report.py 13 Jul 2003 09:05:03 -0000 1.2 *************** *** 22,25 **** --- 22,29 ---- # + """ + This module is tightly coupled with engine.py, and nothing from engine.py + that is used here should be considered a stable API. + """ def createReport(deviceInfos, conflicts, checkConflictsOnly): |
From: <luc...@us...> - 2003-07-13 09:04:18
|
Update of /cvsroot/zxsync/zXSync/zxsync In directory sc8-pr-cvs1:/tmp/cvs-serv29461 Added Files: backup.py Log Message: - Added automatic backups --- NEW FILE: backup.py --- #!/usr/bin/env python # # zXSync backup management. # # Copyright (C) 2003 Andreas Junghans <aj...@lu...> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # $Id: backup.py,v 1.1 2003/07/13 09:04:15 lucidcake Exp $ # """ This module is tightly coupled with engine.py, and nothing from engine.py that is used here should be considered a stable API. """ from cPickle import dump from cPickle import load import os import os.path import re import string import sys import time # compile regular expressions for finding existing backup files preSyncRE = re.compile("\\A\\d{8}-\\d{6}-\\d{4}-pre-sync.data\\Z") postSyncRE = re.compile("\\A\\d{8}-\\d{6}-\\d{4}-post-sync.data\\Z") # determine the base path to use for the operating system basePath = "." # TODO: use a better default if sys.platform[:6] == "darwin": basePath = os.path.expanduser("~/Library/Application Support/zXSync/backup") def createBackup(pluginId, deviceId, app, postSync): """ Creates a backup for the specified application. The directory where backups are stored depends on the operating system. Currently, only Darwin/Mac OS X is supported with a directory of "~/Library/Application Support/zXSync/backup". The structure of the backup directory looks as follows: backup | +-- plugin id | +-- device id | +-- app id | +-- 20030629-135027-0000-pre-sync.data | +-- 20030629-135228-0000-post-sync.data As you can see, backups are created before and after each sync. The pre-sync backups are made whether or not the sync is successful. A post-sync backup with an identical number as an existing pre-sync backup is made after a successful sync. The "postSync" parameter determines whether this is a pre- or post-sync backup. If "postSync" is true, it's a post-sync backup. Only the last 10 pre and post .data files for an application are kept. Everything else is deleted when making a backup. In the future, this number should be made configurable. """ if postSync: prefix = "post" filterRE = postSyncRE else: prefix = "pre" filterRE = preSyncRE appId = app.getId() # determine the backup path for the application appPath = os.path.join(basePath, pluginId, deviceId, appId) if not os.path.exists(appPath): os.makedirs(appPath, 0700) # get a list of entries in that path and mask out everything # that's irrelevant for zXSync unFilteredEntries = os.listdir(appPath) backups = filter(lambda x: len(filterRE.findall(x)) == 1, unFilteredEntries) backups.sort() # delete old backups removeCount = len(backups) - 10 + 1 # +1 because we make a new backup later on for index in range(removeCount): os.remove(os.path.join(appPath, backups[0])) del backups[0] # determine the file name to use backupName = time.strftime("%Y%m%d-%H%M%S") backupNumber = 0 for index in range(len(backups)-1, -1, -1): check = backups[index][:15] if check < backupName: break # note: this code assumes that there may be backup names # for earlier and _later_ times (e.g. when changing the # system clock) if check == backupName: backupNumber = int(backups[index][16:20]) + 1 if backupNumber >= 0000: backupNumber = 0 # delete all previous backups to prevent # sorting problems - this is not really # supposed to happen (10000 backups per second!) for delIndex in range(index, -1, -1): check = backups[delIndex][:15] if check == backupName: os.remove(os.path.join(appPath, backups[delIndex])) del backups[delIndex] else: break break backupName += "-" + string.zfill(backupNumber, 4) + "-" + prefix + "-sync.data" # actually make the backup backupFile = open(os.path.join(appPath, backupName), "wb") try: dump(app, backupFile, 1) finally: backupFile.close() def createBackups(deviceInfos, appToSync, postSync): """ Creates backups for all deviceInfo objects in the specified sequence (but only for the specified application). """ if postSync: prefix = "post" filterRE = postSyncRE else: prefix = "pre" filterRE = preSyncRE for deviceInfo in deviceInfos: # determine the intermediate path components pluginId = deviceInfo.plugin.__name__ deviceId = deviceInfo.device.getId() # make backups of all apps for app in deviceInfo.data: if app.getId() == appToSync: createBackup(pluginId, deviceId, app, postSync) def loadBackup(pluginId, deviceId, appId, postSync): """ Loads the latest available backup for the specified plugin, device, and application. If no backup is found, None is returned. """ if postSync: prefix = "post" filterRE = postSyncRE else: prefix = "pre" filterRE = preSyncRE # determine the backup path for the application appPath = os.path.join(basePath, pluginId, deviceId, appId) if not os.path.exists(appPath): return None # determine the latest backup file unFilteredEntries = os.listdir(appPath) backups = filter(lambda x: len(filterRE.findall(x)) == 1, unFilteredEntries) backups.sort() if len(backups) == 0: return None # load the backup backupFile = open(os.path.join(appPath, backups[-1]), "rb") try: retVal = load(backupFile) finally: backupFile.close() return retVal def loadBackups(deviceInfos, appToSync, postSync): """ Loads the latest available backups for all applications in the specified list of device infos (but only for the specified application). The return value is a dictionary with a (plugin id, device id) tuple as keys and lists of Application instances as values. """ if postSync: prefix = "post" filterRE = postSyncRE else: prefix = "pre" filterRE = preSyncRE retVal = {} for deviceInfo in deviceInfos: # determine the intermediate path components pluginId = deviceInfo.plugin.__name__ deviceId = deviceInfo.device.getId() appList = [] # make backups of all apps for app in deviceInfo.data: appId = app.getId() if appId != appToSync: continue # try to load the backup backup = loadBackup(pluginId, deviceId, appId, postSync) if backup != None: appList.append(backup) # append the app list to the dictionary if len(appList) > 0: retVal[(pluginId, deviceId)] = appList return retVal |
From: <luc...@us...> - 2003-07-13 09:02:52
|
Update of /cvsroot/zxsync/zXSync/plugins/zaurus In directory sc8-pr-cvs1:/tmp/cvs-serv29341 Modified Files: zaurusplugin.py Log Message: - Added the notion of device ids (necessary for backups) - Added copyright line (Geoff: I just add my copyright to every file I touch - I hope this is OK, and you're of course invited to do the same) Index: zaurusplugin.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/zaurus/zaurusplugin.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** zaurusplugin.py 10 May 2003 00:23:07 -0000 1.6 --- zaurusplugin.py 13 Jul 2003 09:02:50 -0000 1.7 *************** *** 4,7 **** --- 4,8 ---- # # Copyright (C) 2003 Geoff Beier <ge...@mo...> + # Copyright (C) 2003 Andreas Junghans <aj...@lu...> # # This library is free software; you can redistribute it and/or *************** *** 86,89 **** --- 87,99 ---- return 1 + + def getId(self): + """ + Use the IP of the Zaurus as id (may not be reliable, but I can't + think of something better right now). + """ + return self.ip_address + + def init(self, context): """Initiate a QCOP connection and get handshake and sync info""" |
From: <luc...@us...> - 2003-07-13 09:00:10
|
Update of /cvsroot/zxsync/zXSync/plugins/zaurus In directory sc8-pr-cvs1:/tmp/cvs-serv28944 Modified Files: zauruscontacts.py Log Message: - Removed UID field from vCards (the id is still available via getId(), but not as a field). This avoids a lot of trouble when the ids of a plugin are not worth much (as is currently the case with iPod and Zaurus contacts ;-)) - Added check so no field is written more than once Index: zauruscontacts.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/zaurus/zauruscontacts.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** zauruscontacts.py 23 Jun 2003 21:27:40 -0000 1.3 --- zauruscontacts.py 13 Jul 2003 09:00:03 -0000 1.4 *************** *** 86,90 **** supportedFields = \ [X_ZAURUS_BIRTHDAY, X_ZAURUS_CATEGORIES, X_ZAURUS_UNKNOWN, ! vcard.UID, vcard.N, vcard.FN, vcard.NICKNAME, vcard.BDAY, vcard.ADR, vcard.TEL, vcard.EMAIL, vcard.NOTE, vcard.ORG, vcard.TITLE, vcard.URL, vcard.X_URL_HOME, vcard.X_URL_WORK --- 86,90 ---- supportedFields = \ [X_ZAURUS_BIRTHDAY, X_ZAURUS_CATEGORIES, X_ZAURUS_UNKNOWN, ! vcard.N, vcard.FN, vcard.NICKNAME, vcard.BDAY, vcard.ADR, vcard.TEL, vcard.EMAIL, vcard.NOTE, vcard.ORG, vcard.TITLE, vcard.URL, vcard.X_URL_HOME, vcard.X_URL_WORK *************** *** 147,160 **** - def addField(xmlString, fieldName, value): - """ - Adds a field to an XML string (as attribute value). - If the value is None or "", nothing is added. - """ - if value == None or value == "": - return xmlString - return xmlString + fieldName + '="' + zaurusutils.zaurusEscape(value) + '" ' - - class ZaurusContactsError(PluginError): """ --- 147,150 ---- *************** *** 352,355 **** --- 342,355 ---- + def addField(self, xmlString, fieldName, value): + """ + Adds a field to an XML string (as attribute value). + If the value is None or "", nothing is added. + """ + if value == None or value == "" or fieldName in self.writtenFields: + return xmlString + return xmlString + fieldName + '="' + zaurusutils.zaurusEscape(value) + '" ' + + def writeAllEntries(self, entries): """ *************** *** 364,370 **** # break entryXML = '<Contact rid="' + str(currentRid) + '" rinfo="1" ' # UID field ! entryXML = addField(entryXML, UID, entry.getUID().getValue()) # N field --- 364,371 ---- # break entryXML = '<Contact rid="' + str(currentRid) + '" rinfo="1" ' + self.writtenFields = [] # UID field ! entryXML = self.addField(entryXML, UID, entry.getId()) # N field *************** *** 372,385 **** if nameField != None: nameValue = nameField.getValue() ! entryXML = addField(entryXML, LAST_NAME, nameValue[0][0]) ! entryXML = addField(entryXML, FIRST_NAME, nameValue[1][0]) ! entryXML = addField(entryXML, MIDDLE_NAME, nameValue[2][0]) ! entryXML = addField(entryXML, TITLE, nameValue[3][0]) ! entryXML = addField(entryXML, SUFFIX, nameValue[4][0]) # FN field formattedNameField = entry.getFormattedName() if formattedNameField != None: ! entryXML = addField(entryXML, FILE_AS, formattedNameField.getValue()) --- 373,386 ---- if nameField != None: nameValue = nameField.getValue() ! entryXML = self.addField(entryXML, LAST_NAME, nameValue[0][0]) ! entryXML = self.addField(entryXML, FIRST_NAME, nameValue[1][0]) ! entryXML = self.addField(entryXML, MIDDLE_NAME, nameValue[2][0]) ! entryXML = self.addField(entryXML, TITLE, nameValue[3][0]) ! entryXML = self.addField(entryXML, SUFFIX, nameValue[4][0]) # FN field formattedNameField = entry.getFormattedName() if formattedNameField != None: ! entryXML = self.addField(entryXML, FILE_AS, formattedNameField.getValue()) *************** *** 387,391 **** nicknameField = entry.getNickname() if nicknameField != None: ! entryXML = addField(entryXML, NICKNAME, nicknameField.getValue()[0]) --- 388,392 ---- nicknameField = entry.getNickname() if nicknameField != None: ! entryXML = self.addField(entryXML, NICKNAME, nicknameField.getValue()[0]) *************** *** 393,397 **** birthdayField = entry.getChildWithId(X_ZAURUS_BIRTHDAY) if birthdayField != None: ! entryXML = addField(entryXML, BIRTHDAY, birthdayField.getValue()) else: birthdayField = entry.getBirthday() --- 394,398 ---- birthdayField = entry.getChildWithId(X_ZAURUS_BIRTHDAY) if birthdayField != None: ! entryXML = self.addField(entryXML, BIRTHDAY, birthdayField.getValue()) else: birthdayField = entry.getBirthday() *************** *** 401,405 **** birthdayValue = time.strftime(DATE_FORMATS[0], birthdayTuple) # assume that gmtime should be stored on the Z ! entryXML = addField(entryXML, BIRTHDAY, birthdayValue) # ADR fields --- 402,406 ---- birthdayValue = time.strftime(DATE_FORMATS[0], birthdayTuple) # assume that gmtime should be stored on the Z ! entryXML = self.addField(entryXML, BIRTHDAY, birthdayValue) # ADR fields *************** *** 409,423 **** addressTypes = addressField.getTypes() if zxsync.vcard.WORK in addressTypes: ! entryXML = addField(entryXML, BUSINESS_STREET, addressValue[2][0]) ! entryXML = addField(entryXML, BUSINESS_CITY, addressValue[3][0]) ! entryXML = addField(entryXML, BUSINESS_STATE, addressValue[4][0]) ! entryXML = addField(entryXML, BUSINESS_ZIP, addressValue[5][0]) ! entryXML = addField(entryXML, BUSINESS_COUNTRY, addressValue[6][0]) if zxsync.vcard.HOME in addressTypes: ! entryXML = addField(entryXML, HOME_STREET, addressValue[2][0]) ! entryXML = addField(entryXML, HOME_CITY, addressValue[3][0]) ! entryXML = addField(entryXML, HOME_STATE, addressValue[4][0]) ! entryXML = addField(entryXML, HOME_ZIP, addressValue[5][0]) ! entryXML = addField(entryXML, HOME_COUNTRY, addressValue[6][0]) # TEL fields --- 410,424 ---- addressTypes = addressField.getTypes() if zxsync.vcard.WORK in addressTypes: ! entryXML = self.addField(entryXML, BUSINESS_STREET, addressValue[2][0]) ! entryXML = self.addField(entryXML, BUSINESS_CITY, addressValue[3][0]) ! entryXML = self.addField(entryXML, BUSINESS_STATE, addressValue[4][0]) ! entryXML = self.addField(entryXML, BUSINESS_ZIP, addressValue[5][0]) ! entryXML = self.addField(entryXML, BUSINESS_COUNTRY, addressValue[6][0]) if zxsync.vcard.HOME in addressTypes: ! entryXML = self.addField(entryXML, HOME_STREET, addressValue[2][0]) ! entryXML = self.addField(entryXML, HOME_CITY, addressValue[3][0]) ! entryXML = self.addField(entryXML, HOME_STATE, addressValue[4][0]) ! entryXML = self.addField(entryXML, HOME_ZIP, addressValue[5][0]) ! entryXML = self.addField(entryXML, HOME_COUNTRY, addressValue[6][0]) # TEL fields *************** *** 429,452 **** phoneAdded = 0 if zxsync.vcard.FAX in phoneTypes: ! entryXML = addField(entryXML, HOME_FAX, phoneValue) phoneAdded = 1 if zxsync.vcard.CELL in phoneTypes: ! entryXML = addField(entryXML, HOME_MOBILE, phoneValue) phoneAdded = 1 if (not (zxsync.vcard.PAGER) in phoneTypes) and (not phoneAdded): ! entryXML = addField(entryXML, HOME_PHONE, phoneValue) if zxsync.vcard.WORK in phoneTypes: phoneAdded = 0 if zxsync.vcard.FAX in phoneTypes: ! entryXML = addField(entryXML, BUSINESS_FAX, phoneValue) phoneAdded = 1 if zxsync.vcard.CELL in phoneTypes: ! entryXML = addField(entryXML, BUSINESS_MOBILE, phoneValue) phoneAdded = 1 if zxsync.vcard.PAGER in phoneTypes: ! entryXML = addField(entryXML, BUSINESS_PAGER, phoneValue) phoneAdded = 1 if not phoneAdded: ! entryXML = addField(entryXML, BUSINESS_PHONE, phoneValue) # EMAIL fields --- 430,453 ---- phoneAdded = 0 if zxsync.vcard.FAX in phoneTypes: ! entryXML = self.addField(entryXML, HOME_FAX, phoneValue) phoneAdded = 1 if zxsync.vcard.CELL in phoneTypes: ! entryXML = self.addField(entryXML, HOME_MOBILE, phoneValue) phoneAdded = 1 if (not (zxsync.vcard.PAGER) in phoneTypes) and (not phoneAdded): ! entryXML = self.addField(entryXML, HOME_PHONE, phoneValue) if zxsync.vcard.WORK in phoneTypes: phoneAdded = 0 if zxsync.vcard.FAX in phoneTypes: ! entryXML = self.addField(entryXML, BUSINESS_FAX, phoneValue) phoneAdded = 1 if zxsync.vcard.CELL in phoneTypes: ! entryXML = self.addField(entryXML, BUSINESS_MOBILE, phoneValue) phoneAdded = 1 if zxsync.vcard.PAGER in phoneTypes: ! entryXML = self.addField(entryXML, BUSINESS_PAGER, phoneValue) phoneAdded = 1 if not phoneAdded: ! entryXML = self.addField(entryXML, BUSINESS_PHONE, phoneValue) # EMAIL fields *************** *** 461,482 **** emails += emailValue if zxsync.vcard.PREF in emailTypes and not defaultAdded: ! entryXML = addField(entryXML, DEFAULT_EMAIL, emailValue) defaultAdded = 1 ! entryXML = addField(entryXML, EMAILS, emails) # NOTE fields noteFields = entry.getNotes() if len(noteFields) > 0: ! entryXML = addField(entryXML, NOTES, noteFields[0].getValue()) # ORG fields orgFields = entry.getOrganizations() if len(orgFields) > 0: ! entryXML = addField(entryXML, COMPANY, orgFields[0].getValue()[0]) # TITLE fields titleFields = entry.getTitles() if len(titleFields) > 0: ! entryXML = addField(entryXML, JOB_TITLE, titleFields[0].getValue()) # URL fields --- 462,483 ---- emails += emailValue if zxsync.vcard.PREF in emailTypes and not defaultAdded: ! entryXML = self.addField(entryXML, DEFAULT_EMAIL, emailValue) defaultAdded = 1 ! entryXML = self.addField(entryXML, EMAILS, emails) # NOTE fields noteFields = entry.getNotes() if len(noteFields) > 0: ! entryXML = self.addField(entryXML, NOTES, noteFields[0].getValue()) # ORG fields orgFields = entry.getOrganizations() if len(orgFields) > 0: ! entryXML = self.addField(entryXML, COMPANY, orgFields[0].getValue()[0]) # TITLE fields titleFields = entry.getTitles() if len(titleFields) > 0: ! entryXML = self.addField(entryXML, JOB_TITLE, titleFields[0].getValue()) # URL fields *************** *** 486,494 **** if len(homeURLFields) > 0: homeURL = homeURLFields[0].getValue() ! entryXML = addField(entryXML, HOME_WEB_PAGE, homeURL) workURLFields = entry.getWorkURLs() if len(workURLFields) > 0: workURL = workURLFields[0].getValue() ! entryXML = addField(entryXML, BUSINESS_WEB_PAGE, workURL) if homeURL == None: urlFields = entry.getURLs() --- 487,495 ---- if len(homeURLFields) > 0: homeURL = homeURLFields[0].getValue() ! entryXML = self.addField(entryXML, HOME_WEB_PAGE, homeURL) workURLFields = entry.getWorkURLs() if len(workURLFields) > 0: workURL = workURLFields[0].getValue() ! entryXML = self.addField(entryXML, BUSINESS_WEB_PAGE, workURL) if homeURL == None: urlFields = entry.getURLs() *************** *** 496,500 **** url = urlField.getValue() if url != workURL: ! entryXML = addField(entryXML, HOME_WEB_PAGE, url) break --- 497,501 ---- url = urlField.getValue() if url != workURL: ! entryXML = self.addField(entryXML, HOME_WEB_PAGE, url) break *************** *** 505,509 **** if fieldId != None: if fieldId.find(X_ZAURUS_UNKNOWN) == 0: ! entryXML = addField(entryXML, fieldId[len(X_ZAURUS_UNKNOWN):], field.getValue()) entriesXML += entryXML --- 506,510 ---- if fieldId != None: if fieldId.find(X_ZAURUS_UNKNOWN) == 0: ! entryXML = self.addField(entryXML, fieldId[len(X_ZAURUS_UNKNOWN):], field.getValue()) entriesXML += entryXML |
From: <luc...@us...> - 2003-07-13 08:57:41
|
Update of /cvsroot/zxsync/zXSync/plugins/osx In directory sc8-pr-cvs1:/tmp/cvs-serv28758 Modified Files: osxplugin.py Log Message: - Removed UID field from vCards (the id is still available via getId(), but not as a field). This avoids a lot of trouble when the ids of a plugin are not worth much (as is currently the case with iPod and Zaurus contacts ;-)) - Added the notion of device ids (necessary for backups) - Added change field notification Index: osxplugin.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/osx/osxplugin.py,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** osxplugin.py 23 Jun 2003 21:25:39 -0000 1.8 --- osxplugin.py 13 Jul 2003 08:57:38 -0000 1.9 *************** *** 74,78 **** record = None try: ! uid = entry.getUID().getValue() record = self.ab.recordForUniqueId(uid) except: --- 74,78 ---- record = None try: ! uid = entry.getId() record = self.ab.recordForUniqueId(uid) except: *************** *** 150,153 **** --- 150,161 ---- return contacts.notifyAddField(newField, parentEntry) + + def notifyChangeField(self, newField, oldField): + """ + Called to notify the plugin when a field is about to be changed in + zXSync's internal pool of data for this application. + """ + return contacts.notifyChangeField(newField, oldField) + class OSXDevice(Device): *************** *** 157,160 **** --- 165,177 ---- """ + def getId(self): + """ + Returns the id of this device. For now, we have only the local + machine as a device, so "localhost" seems like an appropriate + choice. + """ + return "localhost" + + def init(self, context): """ *************** *** 179,185 **** """ ! # For the osx plugin, the implementation is really simple: If we're ! # running under osx, return a "device" for every entry in the settings ! # parameter. If not, return an empty list. devices = [] if sys.platform[:6] == "darwin": --- 196,202 ---- """ ! # Return exactly one "device" if we're running on a Mac (and we have at ! # least one settings dictionary). Once some networking support is in ! # place, it should be possible to return more than one device. devices = [] if sys.platform[:6] == "darwin": *************** *** 187,190 **** --- 204,208 ---- device = OSXDevice(settingsDict) devices.append(device) + break return devices |
From: <luc...@us...> - 2003-07-13 08:55:22
|
Update of /cvsroot/zxsync/zXSync/plugins/osx In directory sc8-pr-cvs1:/tmp/cvs-serv28517 Modified Files: ipodplugin.py Log Message: - Added the notion of device ids (necessary for backups) Index: ipodplugin.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/osx/ipodplugin.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** ipodplugin.py 23 Jun 2003 21:24:44 -0000 1.5 --- ipodplugin.py 13 Jul 2003 08:55:19 -0000 1.6 *************** *** 219,222 **** --- 219,229 ---- """ + def getId(self): + """ + Returns the id of the device (the iPod name is used here). + """ + return iPodName(self.settings) + + def init(self, context): """ |
From: <luc...@us...> - 2003-07-13 08:53:22
|
Update of /cvsroot/zxsync/zXSync/plugins/osx In directory sc8-pr-cvs1:/tmp/cvs-serv28147 Modified Files: contacts.py Log Message: - Removed UID field from vCards (the id is still available via getId(), but not as a field). This avoids a lot of trouble when the ids of a plugin are not worth much (as is currently the case with iPod and Zaurus contacts ;-)) - Set the sync mode of FN to SYNC_TO by default (FN is generated on the Mac, and there's no point in letting this conflict with other devices) - If a field is not supported, reject the change (FN is an example for that) Index: contacts.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/osx/contacts.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** contacts.py 23 Jun 2003 21:23:26 -0000 1.5 --- contacts.py 13 Jul 2003 08:53:18 -0000 1.6 *************** *** 32,36 **** supportedFields = \ [X_PREF, ! vcard.UID, vcard.N, vcard.NICKNAME, vcard.BDAY, vcard.ADR, vcard.TEL, vcard.EMAIL, vcard.NOTE, vcard.ORG, vcard.TITLE, vcard.URL, vcard.X_AIM, vcard.X_ICQ, vcard.X_JABBER, vcard.X_MSN, vcard.X_YAHOO --- 32,36 ---- supportedFields = \ [X_PREF, ! vcard.N, vcard.NICKNAME, vcard.BDAY, vcard.ADR, vcard.TEL, vcard.EMAIL, vcard.NOTE, vcard.ORG, vcard.TITLE, vcard.URL, vcard.X_AIM, vcard.X_ICQ, vcard.X_JABBER, vcard.X_MSN, vcard.X_YAHOO *************** *** 88,91 **** --- 88,96 ---- person.valueForProperty(addressbook.kABSuffixProperty) ) + # special handling: since FN is just generated, set the field to + # SYNC_TO to avoid conflicts + fnField = personVCard.getChildWithId(vcard.FN) + if fnField != None: + fnField.setSyncMode(zxsync.syncbase.SYNC_TO) # NICKNAME field *************** *** 591,594 **** --- 596,610 ---- return 1 + return 1 + + + def notifyChangeField(newField, oldField): + """ + Called to notify the plugin when a field is about to be changed in + zXSync's internal pool of data for this application. + """ + fieldId = newField.getId() + if not (fieldId in supportedFields): + return 0 return 1 |
From: <luc...@us...> - 2003-06-23 21:27:44
|
Update of /cvsroot/zxsync/zXSync/plugins/zaurus In directory sc8-pr-cvs1:/tmp/cvs-serv12774 Modified Files: zauruscontacts.py Log Message: - Small correction to telephone number handling - Added notification mechanism Index: zauruscontacts.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/zaurus/zauruscontacts.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** zauruscontacts.py 11 May 2003 18:07:40 -0000 1.2 --- zauruscontacts.py 23 Jun 2003 21:27:40 -0000 1.3 *************** *** 28,31 **** --- 28,32 ---- from zxsync import syncbase import zxsync.vcard + from zxsync import vcard ADDRESSBOOK_DIR = "Applications/addressbook" *************** *** 83,86 **** --- 84,133 ---- "%m.%d.%y") + supportedFields = \ + [X_ZAURUS_BIRTHDAY, X_ZAURUS_CATEGORIES, X_ZAURUS_UNKNOWN, + vcard.UID, vcard.N, vcard.FN, vcard.NICKNAME, vcard.BDAY, vcard.ADR, + vcard.TEL, vcard.EMAIL, vcard.NOTE, vcard.ORG, vcard.TITLE, vcard.URL, + vcard.X_URL_HOME, vcard.X_URL_WORK + ] + + + def getTelTypes(vcardTypes): + """ + Returns the Zaurus field names for the types of a TEL field. + For example, if the types are FAX, HOME, and WORK, the returned + sequence contains BUSINESS_FAX and HOME_FAX. + """ + retVal = [] + if zxsync.vcard.HOME in vcardTypes: + found = 0 + if zxsync.vcard.FAX in vcardTypes: + retVal.append(HOME_FAX) + found = 1 + if zxsync.vcard.CELL in vcardTypes: + retVal.append(HOME_MOBILE) + found = 1 + if zxsync.vcard.VOICE in vcardTypes: + retVal.append(HOME_PHONE) + found = 1 + if (not (zxsync.vcard.PAGER in vcardTypes)) and (not found): + retVal.append(HOME_PHONE) + if zxsync.vcard.WORK in vcardTypes: + found = 0 + if zxsync.vcard.FAX in vcardTypes: + retVal.append(BUSINESS_FAX) + found = 1 + if zxsync.vcard.CELL in vcardTypes: + retVal.append(BUSINESS_MOBILE) + found = 1 + if zxsync.vcard.VOICE in vcardTypes: + retVal.append(BUSINESS_PHONE) + found = 1 + if zxsync.vcard.PAGER in vcardTypes: + retVal.append(BUSINESS_PAGER) + found = 1 + if not found: + retVal.append(BUSINESS_PHONE) + return retVal + def getValue(dict, key): *************** *** 387,391 **** entryXML = addField(entryXML, HOME_MOBILE, phoneValue) phoneAdded = 1 ! if zxsync.vcard.VOICE in phoneTypes or not phoneAdded: entryXML = addField(entryXML, HOME_PHONE, phoneValue) if zxsync.vcard.WORK in phoneTypes: --- 434,438 ---- entryXML = addField(entryXML, HOME_MOBILE, phoneValue) phoneAdded = 1 ! if (not (zxsync.vcard.PAGER) in phoneTypes) and (not phoneAdded): entryXML = addField(entryXML, HOME_PHONE, phoneValue) if zxsync.vcard.WORK in phoneTypes: *************** *** 400,404 **** entryXML = addField(entryXML, BUSINESS_PAGER, phoneValue) phoneAdded = 1 ! if zxsync.vcard.VOICE in phoneTypes or not phoneAdded: entryXML = addField(entryXML, BUSINESS_PHONE, phoneValue) --- 447,451 ---- entryXML = addField(entryXML, BUSINESS_PAGER, phoneValue) phoneAdded = 1 ! if not phoneAdded: entryXML = addField(entryXML, BUSINESS_PHONE, phoneValue) *************** *** 476,477 **** --- 523,603 ---- zaurusXML.encode("UTF-8")) + + def notifyAddField(self, newField, parentEntry): + """ + Called to notify the plugin when a field is about to be added to + zXSync's internal pool of data for this application. + """ + fieldId = newField.getId() + if not (fieldId in supportedFields): + return 0 + fieldTypes = newField.getTypes() + sameFields = parentEntry.getChildrenWithId(fieldId) + + # check ADR field + if fieldId == zxsync.vcard.ADR: + fieldOK = 0 + for fieldType in fieldTypes: + if fieldType == zxsync.vcard.WORK or \ + fieldType == zxsync.vcard.HOME: + for address in sameFields: + if fieldType in address.getTypes(): + # only one address of a type is supported + break + else: + fieldOK = 1 + index += 1 + return fieldOK + + # check TEL field + if fieldId == zxsync.vcard.TEL: + zaurusTypes = getTelTypes(fieldTypes) + if len(zaurusTypes) == 0: + return 0 + for phoneNumber in sameFields: + otherZaurusTypes = getTelTypes(phoneNumber.getTypes()) + index = 0 + while index < len(zaurusTypes): + zaurusType = zaurusTypes[index] + if zaurusType in otherZaurusTypes: + # only one number of a certain type + # (e.g. BUSINESS_FAX) is allowed + del zaurusTypes[index] + index -= 1 + index += 1 + return (len(zaurusTypes) > 0) + + # check NOTE field + if fieldId == zxsync.vcard.NOTE: + if len(sameFields) > 0: + return 0 + return 1 + + # check ORG field + if fieldId == zxsync.vcard.ORG: + if len(sameFields) > 0: + return 0 + return 1 + + # check TITLE field + if fieldId == zxsync.vcard.TITLE: + if len(sameFields) > 0: + return 0 + return 1 + + # check URL field + if fieldId == zxsync.vcard.X_URL_HOME: + if len(sameFields) > 0: + return 0 + return 1 + if fieldId == zxsync.vcard.X_URL_WORK: + if len(sameFields) > 0: + return 0 + return 1 + if fieldId == zxsync.vcard.URL: + if len(entry.getChildrenWithId(zxsync.vcard.X_URL_HOME)) > 0: + return 0 + return 1 + + return 1 + |