Logo Search packages:      
Sourcecode: jppy version File versions  Download package

pytype_events.c

#include <Python.h>
#include <datetime.h>

#include <time.h>
#include "pytype_events.h"
#include "pytype_basics.h"
#include "structmember.h"

/*******************************************************
 * Create and delloc methods for objects 
 ******************************************************/

extern PyObject* PyPiEvent_New(PyTypeObject *type, PyObject *args, PyObject *kwds) {
  int i;
  PyPiEvent* self;

  /* Why do we have to do this here? The one in the swig init doesn't seem
     to work ?! */
  PyDateTime_IMPORT;
  
  EventType.ob_type = &PyType_Type;
  self = (PyPiEvent *)type->tp_alloc(type, 0);
  new_Appointment(&(self->a));
  SetBasicRecordObjectAttributeDefaults((PyObject*) self, pack_Appointment);  

  return (PyObject*)self;
}

extern int PyPiEvent_Init(PyObject *self, PyObject *args, PyObject *kwds) {
  PyPiEvent* fromevent = NULL;
  PyPiEvent* event = NULL;
  int i;
  
  static char *kwlist[] = {"event", NULL};
  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, 
                           &fromevent)) {
    return -1;
  }
  
  event = (PyPiEvent*)self;
  /* we have to support calling __init__ more than once */
  free_Appointment(&(event->a));
  if (event->saved_br.size > 0 && event->saved_br.buf) {    
    free(event->saved_br.buf);                              
  }

  if ((fromevent == NULL) || ((PyObject *)fromevent == Py_None)) {
    /* Initialise attributes custom to this type of object */
    new_Appointment(&(event->a));
    SetBasicRecordObjectAttributeDefaults((PyObject*) event, pack_Appointment);    
  } else {
    if (!PyPiEvent_Check(fromevent)) {
      PyErr_SetString(PyExc_TypeError,"Must provide a Event object to share");
      return -1;
    }
  
    /* copy all the database agnostic record attributes */
    event->saved_br.size = fromevent->saved_br.size;
    event->saved_br.attrib = fromevent->saved_br.attrib;
    event->saved_br.rt = fromevent->saved_br.rt;
    event->saved_br.unique_id = fromevent->saved_br.unique_id;

    event->rt = fromevent->rt;
    event->unique_id = fromevent->unique_id;
    
    event->saved_br.buf = malloc(fromevent->saved_br.size);
    memcpy(event->saved_br.buf,
         fromevent->saved_br.buf,
         fromevent->saved_br.size);
    
    event->category = fromevent->category;
    event->unsaved_changes = fromevent->unsaved_changes;
    event->deleted = fromevent->deleted;
    event->modified = fromevent->modified;
    event->busy = fromevent->busy;
    event->secret = fromevent->secret;
    
    /* copy event, begin, end, alarm, advance, advanceUnits,
       repeatType, repeatForever, repeatFrequency, repeatDay,
       repeatDays, repeatWeekstart and exceptions (note, not
       exception as that is a pointer) */
    memcpy(&(event->a), &(fromevent->a), sizeof(struct Appointment));
    
    /* Now do the pointers */
    
    pyint_strcpy(event->a.description, fromevent->a.description);
    pyint_strcpy(event->a.note, fromevent->a.note);
    event->a.exception = malloc(sizeof(struct tm) * fromevent->a.exceptions);
    for (i = 0; i < fromevent->a.exceptions; i++) {
      memcpy(&(event->a.exception[i]), &(fromevent->a.exception[i]), sizeof(struct tm));
    }
  }

  return 0;
}

static PyObject * PyPiEvent_Allocate(PyTypeObject *type, int nitems) {
  PyPiEvent *event;
  if (type == &EventType) {
    event = PyObject_New(PyPiEvent, &EventType);
    return (PyObject *) event;
  } else {
    /* Is this for subclasses ? */
    event = (PyPiEvent *)PyType_GenericAlloc(type, nitems);
    return (PyObject*)event;
  }
}

extern PyObject* PyPiEvent_Wrap(struct Appointment* a, PCRecType rt, 
                         unsigned int unique_id, unsigned char attrib,
                         int size, void* buf) {
  PyPiEvent* event;
  int i;

  event = (PyPiEvent*)PyPiEvent_New(&EventType,NULL,NULL);

  /* copy indefinite, tm, priority and complete */
  memcpy(&(event->a), a, sizeof(struct Appointment));


  /* set saved_br stuff, and rt and unique_id, and attrib derived
     details for the current event */
  SetSavedBrAndRTandUniqueIDandAttribs(rt, unique_id, attrib, size, buf, (PyObject *)event);

  pyp_strcpy(event->a.description, a->description);
  pyp_strcpy(event->a.note, a->note);
  event->a.exception = malloc(sizeof(struct tm) * a->exceptions);
  for (i = 0; i < a->exceptions; i++) {
    memcpy(&(event->a.exception[i]), &(a->exception[i]), sizeof(struct tm));
  }
  
  return (PyObject*)event;
}

static void PyPiEvent_Dealloc(PyPiEvent* self) {
  free_Appointment(&(self->a));
  if (self->saved_br.size > 0 && self->saved_br.buf) {
    free(self->saved_br.buf);
  }
  self->ob_type->tp_free((PyObject*)self);
}


static int PyPiEvent_Compare(PyPiEvent* self,PyPiEvent *other) {
  time_t s, o;

  s = mktime(&(self->a.begin));
  o = mktime(&(other->a.begin));

  if (s == o) {
    return 0;
  } else if (s > 0) {
    return -1;
  } else {
    return 1;
  };
}

static char *PyPiEvent_key_list[] = {
  "description",
  "note",
  "begin",
  "end",
  "alarm",
  "dates",
  "final",
  NULL};

static PyObject* PyPiEvent_keys(PyObject* self) {
  PyObject *list = PyList_New(0);
  int n = 0;

  while (PyPiEvent_key_list[n]) {
    PyObject *value;
    value = PyString_FromString(PyPiEvent_key_list[n++]);
    PyList_Append(list, value);
    Py_DECREF(value);
  }
  return list;
}

PyObject *PyPiEvent_GetItem(PyPiEvent* self,  PyObject* key);

static PyObject* PyPiEvent_values(PyObject* self) {
  PyObject *list = PyList_New(0);
  int n = 0;

  while (PyPiEvent_key_list[n]) {
    PyObject *key;
    PyObject *value;
    key   = PyString_FromString(PyPiEvent_key_list[n++]);
    value = PyPiEvent_GetItem((PyPiEvent *)self, key);
    PyList_Append(list, value);
    Py_DECREF(key);
    Py_DECREF(value);
  }
  return list;
}

static PyObject* PyPiEvent_items(PyObject* self) {
  PyObject *list = PyList_New(0);
  int n = 0;

  while (PyPiEvent_key_list[n]) {
    PyObject *key, *value, *tuple;
    key = PyString_FromString(PyPiEvent_key_list[n++]);
    value = PyPiEvent_GetItem((PyPiEvent *)self, key);
    tuple = Py_BuildValue("(OO)", key, value);
    PyList_Append(list, tuple); /* get it's own ref */
    Py_DECREF(key);
    Py_DECREF(value);
    Py_DECREF(tuple);
  }
  return list;
}

/*******************************************************
 * 
 ******************************************************/

static PyMethodDef PyPiEvent_Methods[] = {
  { "keys", (PyCFunction)PyPiEvent_keys, METH_NOARGS, "Return a list of available keys"},
  { "items",(PyCFunction)PyPiEvent_items, METH_NOARGS, "Return a list of available items"},
  { "values",(PyCFunction)PyPiEvent_values, METH_NOARGS, "Return a list of available items"},
  {NULL,NULL} /* Sentinel */
};

static PyMemberDef PyPiEvent_Members[] = {
  PYPI_MEMBERS_HEAD,
  {NULL}  /* Sentinel */
};

static PyGetSetDef PyPiEvent_Getseters[] = {
  PYPI_GETSETERS_HEAD,
  {NULL}  /* Sentinel */
};

/**** mapping interface ****/
int PyPiEvent_Len(self) {
  return 7;
}

PyObject *PyPiEvent_GetItem(PyPiEvent* self,  PyObject* key) {
  char *keystring;
  if (!PyString_Check(key)) {
    Py_INCREF(Py_None);
    return Py_None;  
  }

  Py_INCREF(key);
  keystring = PyString_AsString(key);

  GET_STRING_ATTR(keystring,"description", a.description);
  GET_STRING_ATTR(keystring,"note", a.note);

  if (strcasecmp(keystring,"dates") == 0) {
    PyObject *dateutil_rrule_mod, *dateutil_rrule_dict;
    PyObject *rruleset, *rrule;
    PyObject *function, *result;
    PyObject *basicRepeat;
    PyObject *skipDate;
    PyObject *args, *kwargs;
    PyObject *interval;
    int i;

    Py_DECREF(key);
    dateutil_rrule_mod = PyImport_Import(PyString_FromString("dateutil.rrule"));    
    if (dateutil_rrule_mod == NULL) {
      return NULL;
    }
    // printf("Getting dateutil.rule dictionary\n");
    dateutil_rrule_dict = PyModule_GetDict(dateutil_rrule_mod);
    if (dateutil_rrule_dict == NULL) {
      return NULL;
    }
    Py_INCREF(dateutil_rrule_dict);
    Py_DECREF(dateutil_rrule_mod);
    function = PyDict_GetItemString(dateutil_rrule_dict, "rruleset"); /* borrowed reference */
    if (function == NULL) {
      return NULL;
    }
    Py_INCREF(function);
    // printf("Making rruleset\n");
    rruleset = PyObject_CallFunction(function,"(i)",1); // with caching
    if (rruleset == NULL) {
      // printf("Making rruleset failed\n");
      return NULL;
    }
    // printf("Made rruleset\n");    
    Py_INCREF(rruleset);
    // printf("freeing function\n");
    Py_DECREF(function);
    // printf("freed function\n");
    kwargs = PyDict_New();
    // printf("Populating kwargs\n");
    switch (self->a.repeatType) {
      PyObject *repeatList;
      PyObject *weekdayConstant;
      PyObject *weekdayConstantWithWeek;
      int week;
    case repeatNone:
      // printf("has no repeat, so almost empty rruleset\n");
      Py_DECREF(dateutil_rrule_dict);
      {
      PyObject *dtstart;
      dtstart = PyDateTime_FromDateAndTime(self->a.begin.tm_year + 1900,
                                   self->a.begin.tm_mon + 1,
                                   self->a.begin.tm_mday,
                                   self->a.begin.tm_hour,
                                   self->a.begin.tm_min,
                                   self->a.begin.tm_sec,
                                   0);
      PyDict_SetItemString(kwargs,"dtstart",dtstart);
      result = PyObject_CallMethod(rruleset,"rdate","(O)",dtstart);
      if (result == NULL) {
        Py_DECREF(dtstart);
        return NULL;
      }
      Py_DECREF(dtstart);
      }
      return rruleset;
      break;
    case repeatDaily:
      basicRepeat = PyDict_GetItemString(dateutil_rrule_dict, "DAILY");
      Py_INCREF(basicRepeat);
      break;
    case repeatWeekly:
      //printf("repeatWeekly\n");
      basicRepeat = PyDict_GetItemString(dateutil_rrule_dict, "WEEKLY");
      Py_INCREF(basicRepeat);
      repeatList = PyList_New(0);
      for (i=0; i<7; i++) {
      int m;
      if(self->a.repeatDays[i]) {
        //printf("repeatDays[%d] is true\n", i);
        m = i-1;
        if (m < 0) {m = 7;}
        PyList_Append(repeatList, Py_BuildValue("i",m));
      }
      }
      PyDict_SetItemString(kwargs,"byweekday",repeatList);
      Py_DECREF(repeatList);
      break;
    case repeatMonthlyByDay:
      //printf("repeatMonthlyByDay\n");
      basicRepeat = PyDict_GetItemString(dateutil_rrule_dict, "MONTHLY");
      Py_INCREF(basicRepeat);
      //printf("repeatMonthlyByDay repeatDay=%d\n", self->a.repeatDay);
      switch (self->a.repeatDay % 7) {
      case 0:
      weekdayConstant = PyDict_GetItemString(dateutil_rrule_dict, "SU");
      break;
      case 1:
      weekdayConstant = PyDict_GetItemString(dateutil_rrule_dict, "MO");
      break;
      case 2:
      weekdayConstant = PyDict_GetItemString(dateutil_rrule_dict, "TU");
      break;
      case 3:
      weekdayConstant = PyDict_GetItemString(dateutil_rrule_dict, "WE");
      break;
      case 4:
      weekdayConstant = PyDict_GetItemString(dateutil_rrule_dict, "TH");
      break;
      case 5:
      weekdayConstant = PyDict_GetItemString(dateutil_rrule_dict, "FR");
      break;
      case 6:
      weekdayConstant = PyDict_GetItemString(dateutil_rrule_dict, "SA");
      break;
      }
      Py_INCREF(weekdayConstant);
      week = self->a.repeatDay / 7;
      if (week == 4){
      week = -2;  // we +1 soon, and want -1.
      }
      //printf("repeatMonthlyByDay week = %d\n", week);
      weekdayConstantWithWeek = PyObject_CallFunction(weekdayConstant,
                                          "(i)",
                                          week+1);
      Py_INCREF(weekdayConstantWithWeek);
      PyDict_SetItemString(kwargs,"byweekday",weekdayConstantWithWeek);
      Py_DECREF(weekdayConstantWithWeek);
      Py_DECREF(weekdayConstant);
      break;
    case repeatMonthlyByDate:
      basicRepeat = PyDict_GetItemString(dateutil_rrule_dict, "MONTHLY");
      Py_INCREF(basicRepeat);
      break;
    case repeatYearly:
      basicRepeat = PyDict_GetItemString(dateutil_rrule_dict, "YEARLY");
      Py_INCREF(basicRepeat);
      break;
    }
    Py_DECREF(dateutil_rrule_dict);
    // printf("Populating interval %d into kwargs\n", self->a.repeatFrequency);
    interval = Py_BuildValue("i",self->a.repeatFrequency);
    PyDict_SetItemString(kwargs,"interval",interval);
    Py_DECREF(interval);
    {
      PyObject *dtstart;
      dtstart = PyDateTime_FromDateAndTime(self->a.begin.tm_year + 1900,
                                 self->a.begin.tm_mon + 1,
                                 self->a.begin.tm_mday,
                                 self->a.begin.tm_hour,
                                 self->a.begin.tm_min,
                                 self->a.begin.tm_sec,
                                 0);
      PyDict_SetItemString(kwargs,"dtstart",dtstart);
      Py_DECREF(dtstart);
    }
    if (!(self->a.repeatForever)) {
      PyObject *untildatetime;
      untildatetime = PyDate_FromDate(self->a.repeatEnd.tm_year + 1900,
                              self->a.repeatEnd.tm_mon + 1,
                              self->a.repeatEnd.tm_mday);
      PyDict_SetItemString(kwargs,"until",untildatetime);
      Py_DECREF(untildatetime);
    }
    {
      PyObject *wkst;
      wkst = Py_BuildValue("i",self->a.repeatWeekstart);
      PyDict_SetItemString(kwargs,"wkst",wkst);
      Py_DECREF(wkst);
    }

    // printf("Going to fetch rrule function\n");
    function = PyDict_GetItemString(dateutil_rrule_dict, "rrule"); /* borrowed reference */
    if (function == NULL) {
      return NULL;
    }
    // printf("Going to incref function\n");
    Py_INCREF(function);
    // printf("Going to call rrule function\n");
    args   = Py_BuildValue("(O)",basicRepeat);
    rrule = PyObject_Call(function, args, kwargs);
    if (rrule == NULL) {
      return NULL;
    }
    Py_INCREF(rrule);
    Py_DECREF(args);
    Py_DECREF(kwargs);
    Py_DECREF(function);

    // printf("Going to call rruleset.rrule function\n");
    result = PyObject_CallMethod(rruleset,"rrule","(O)",rrule);
    if (result == NULL) {
      return NULL;
    }
    Py_DECREF(result);
    Py_DECREF(rrule);

    for (i = 0; i < self->a.exceptions; i++) {
      skipDate = PyDateTime_FromDateAndTime(self->a.exception[i].tm_year + 1900,
                                  self->a.exception[i].tm_mon + 1,
                                  self->a.exception[i].tm_mday,
                                  0,0,0,0);
      result = PyObject_CallMethod(rruleset,"exdate","(O)",skipDate);
      if (result == NULL) {
      Py_DECREF(skipDate);
      return NULL;
      }
      Py_DECREF(result);
      Py_DECREF(skipDate);
    }
    return rruleset;
  }

  if (strcasecmp(keystring,"alarm") == 0) {
    PyObject *units;
    Py_DECREF(key);
    if (!(self->a.alarm)) {
      Py_INCREF(Py_None);
      return Py_None;  
    }
    if (self->a.advanceUnits == advMinutes) {
      return PyDelta_FromDSU(0,self->a.advance * 60,0);
    } else if (self->a.advanceUnits == advHours) {
      return PyDelta_FromDSU(0,self->a.advance * 60 * 60,0);
    } else {
      return PyDelta_FromDSU(self->a.advance,0,0);
    }
  }


  if (strcasecmp(keystring,"exceptions") == 0) {
    PyObject *list;
    int i;
    Py_DECREF(key);
    list = PyList_New(self->a.exceptions);    
    for (i = 0; i < self->a.exceptions; i++) {
       PyList_SetItem(list,i,PyDate_FromDate(self->a.exception[i].tm_year + 1900,
                                   self->a.exception[i].tm_mon + 1,
                                   self->a.exception[i].tm_mday));
    }
    return list;
  }

  if (strcasecmp(keystring,"begin") == 0) {
    Py_DECREF(key);
    if (self->a.event) {
      return PyDate_FromDate(self->a.begin.tm_year + 1900,
                       self->a.begin.tm_mon + 1,
                       self->a.begin.tm_mday);
    } else {
      return PyDateTime_FromDateAndTime(self->a.begin.tm_year + 1900,
                              self->a.begin.tm_mon + 1,
                              self->a.begin.tm_mday,
                              self->a.begin.tm_hour,
                              self->a.begin.tm_min,
                              self->a.begin.tm_sec,
                              0);
    }
  }
  if (strcasecmp(keystring,"end") == 0) {
    Py_DECREF(key);
    if (self->a.event) {
      return PyDate_FromDate(self->a.end.tm_year + 1900,
                       self->a.end.tm_mon + 1,
                       self->a.end.tm_mday);
    } else {
      return PyDateTime_FromDateAndTime(self->a.end.tm_year + 1900,
                              self->a.end.tm_mon + 1,
                              self->a.end.tm_mday,
                              self->a.end.tm_hour,
                              self->a.end.tm_min,
                              self->a.end.tm_sec,
                              0);
    }
  }

  if (strcasecmp(keystring,"final") == 0) {
    Py_DECREF(key);
    if (self->a.repeatForever) {
      Py_INCREF(Py_None);
      return Py_None;
    } else {
      return PyDate_FromDate(self->a.repeatEnd.tm_year + 1900,
                       self->a.repeatEnd.tm_mon + 1,
                       self->a.repeatEnd.tm_mday);
    }
  }

  
  PyErr_Format(PyExc_KeyError,"no such key '%s'", keystring);
  Py_DECREF(key);
  return NULL;
}

int PyPiEvent_SetItem(PyPiEvent* self, PyObject* key, PyObject* value) {
  char buf[255];
  char *keystring;

  if (!PyString_Check(key)) {
    PyErr_SetString(PyExc_TypeError,"key must be a String");
    return -1;
  }
  
  Py_INCREF(key);
  keystring = PyString_AsString(key);

  if (value == NULL) {
    PyErr_Format(PyExc_ValueError,"Can't delete value %s", keystring);
    return -1;
  }
  
  SET_STRING_ATTR(keystring,"description",a.description,value, 256);
  SET_STRING_ATTR(keystring,"note",a.note,value, 4096);

  PyErr_SetString(PyExc_KeyError,"no such key");
  Py_DECREF(key);
  return -1;
}

static PyMappingMethods PyPiEvent_Mapping = {
  (inquiry)PyPiEvent_Len,
  (binaryfunc)PyPiEvent_GetItem, 
  (objobjargproc)PyPiEvent_SetItem,
};



/*******************************************************
 * Provide a repr method
 ******************************************************/
static PyObject *PyPiEvent_Repr(PyPiEvent* self) {
  static PyObject *format = NULL;
  PyObject *attrib, *args, *result;
  int len1;
  char time[100];

  if (format == NULL) {
    format = PyString_FromString("<%s '%s' %r %s>");
    if (format == NULL)
      return NULL;
  }

  if (self->a.description) {
    len1 = strlen(self->a.description) > 25 ? 25 : strlen(self->a.description);
  } else {
    len1 = 0;
  }
  
  if (self->a.event) {
    strftime(time, 99, "%x", &(self->a.begin));
  } else {
    strftime(time, 99, "%c", &(self->a.begin));
  }

  args = Py_BuildValue("ss#sO", 
                   (self->ob_type)->tp_name,
                   self->a.description,
                   len1,
                   time,
                   Attribute_Repr((PyObject *)self));

  if (args == NULL)
    return NULL;

  result = PyString_Format(format, args);
  Py_DECREF(args);
  return result;
}


/*******************************************************
 * Declare the type
 ******************************************************/


PyTypeObject EventType = {
  PyObject_HEAD_INIT(NULL)
  0,
  "jppy._jpilot.__jpilot.Event",
  sizeof(PyPiEvent),
  0,
  (destructor)PyPiEvent_Dealloc,      /*tp_dealloc*/
  0,                                /*tp_print*/
  0, /*tp_getattr*/
  0, /*tp_setattr*/
  (cmpfunc)PyPiEvent_Compare,     /*tp_compare*/
  (reprfunc)PyPiEvent_Repr,       /*tp_repr*/
  0,                                /*tp_as_number*/
  0,                                /*tp_as_sequence*/
  &PyPiEvent_Mapping,                                /*tp_as_mapping*/
  0,                                /*tp_hash */
  0,                         /*tp_call*/
  0,                         /*tp_str*/
  0,                         /*tp_getattro*/
  0,                         /*tp_setattro*/
  0,                         /*tp_as_buffer*/
  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
  "Event objects",           /* tp_doc */
  0,                       /* tp_traverse */
  0,                       /* tp_clear */
  0,                       /* tp_richcompare */
  0,                       /* tp_weaklistoffset */
  0,                       /* tp_iter */
  0,                       /* tp_iternext */
  PyPiEvent_Methods,             /* tp_methods */
  PyPiEvent_Members,            /* tp_members */
  PyPiEvent_Getseters,          /* tp_getset */
  0,                         /* tp_base */
  0,                         /* tp_dict */
  0,                         /* tp_descr_get */
  0,                         /* tp_descr_set */
  0,                         /* tp_dictoffset */
  (initproc)PyPiEvent_Init,      /* tp_init */
  (allocfunc)PyPiEvent_Allocate,                 /* tp_alloc */
  (newfunc)PyPiEvent_New,                 /* tp_new */
  0, /* Low-level free-memory routine */
};

Generated by  Doxygen 1.6.0   Back to index