def test_agenda_dataobject_to_dict(self):
     agenda1 = Agenda()
     d1 = agenda1.to_dict()
     self.assertEquals(d1, {'minimum_length': 1})
     agenda2 = Agenda.from_dict(d1)
     d2 = agenda2.to_dict()
     self.assertEquals(d2, d1)
    def test_agenda(self):
        agenda_input = Agenda()
        agenda_input = ds().put(agenda_input)
        agenda_output = ds().get(Agenda, agenda_input.key)

        self.assertEquals(agenda_input.key, agenda_output.key)
        self.assertEquals(agenda_input.to_dict(), agenda_output.to_dict())

        ds().delete(Agenda, agenda_input.key)
 def __init__(self, key=None, minimum_length=None):
     if key:
         self._agenda = ds().get(Agenda, key)
     else:
         self._agenda = Agenda(minimum_length)
         self._agenda = ds().put(self._agenda)
class AgendaController(object):

    def __init__(self, key=None, minimum_length=None):
        if key:
            self._agenda = ds().get(Agenda, key)
        else:
            self._agenda = Agenda(minimum_length)
            self._agenda = ds().put(self._agenda)

    @property
    def key(self):
        return self._agenda.key

    @property
    def minimum_length(self):
        return self._agenda.minimum_length

    @minimum_length.setter
    def minimum_length(self, value):
        self._agenda.minimum_length = value
        self._agenda = ds().put(self._agenda)

    def add_shift(self, start, end):
        shift = Shift(self.key, start, end)
        shift = ds().put(shift)
        return shift

    def del_shift(self, shift_key):
        ds().delete(Shift, shift_key)

    def get_shift(self, shift_key):
        return ds().get(Shift, shift_key)

    def get_shifts_iteritems(self, start=None, end=None):
        for key, shift in self._agenda.iteritems_filter(start, end):
            yield (key, shift)

    def get_shifts_itervalues(self, start=None, end=None):
        for _, shift in self._agenda.iteritems():
            yield shift

    def add_appointment(self, start, end):
        appo = Appointment(None, start, end)
        length = appo.interval.end - appo.interval.start
        for _, shift in self._agenda.iteritems():
            if appo.interval not in shift.interval:
                continue
            if appo.interval not in slots_in_interval(
                                length, shift.interval, self.minimum_length):
                continue
            appos_in_shift = [a.interval for (_, a) in shift.iteritems()]
            if not interval_overlaps(appo.interval, appos_in_shift):
                appo.parent_key = shift.key
                try:
                    appo = ds().put(appo)
                except (OverlappingIntervalWarning, ConcurrencyWarning):
                    appo.parent_key = None
                    continue
                return appo
        raise NotAvailableSlotError

    def del_appointment(self, appo_key):
        ds().delete(Appointment, appo_key)

    def get_appointment(self, appo_key):
        return ds().get(Appointment, appo_key)

    def get_appointments_in_shift_iteritems(self, shift_key):
        for key, appo in ds().get(Shift, shift_key).iteritems():
            yield key, appo

    def get_appointments_iteritems(self, start=None, end=None):
        for _, shift in self._agenda.iteritems_filter(start, end):
            for key, appo in shift.iteritems_filter(start, end):
                yield key, appo

    def get_appointments_itervalues(self, start=None, end=None):
        for _, shift in self._agenda.iteritems():
            for _, appo in shift.iteritems():
                yield appo

    def get_free_slots(self, start, end, length=None):
        """Return slots in shifts which does not overlaps with its
        appointments.
        """
        length = length or self.minimum_length
        interval = Interval(start, end)
        for slot in slots_in_interval(length, interval, length):
            for shift_key, shift in self.get_shifts_iteritems():
                if slot not in shift.interval:
                    continue
                overlapping_appointment = False
                for _, appo in self.get_appointments_in_shift_iteritems(shift_key):
                    if slot.overlaps(appo.interval):
                        overlapping_appointment = True
                        break
                if overlapping_appointment == False:
                    yield slot
                    break

    def destroy(self):
        for (key, shift) in list(self._agenda.iteritems()):
            for (appo_key, _) in list(shift.iteritems()):
                ds().delete(Appointment, appo_key)
            ds().delete(Shift, key)
        ds().delete(Agenda, self.key)