Example #1
0
class SetListEntity(base.TogglEntity):
    field = fields.SetField(required=True)  # type: set
Example #2
0
class TimeEntry(WorkspacedEntity):
    description = fields.StringField()
    """
    Description of the entry.
    """

    project = fields.MappingField(Project, 'pid')
    """
    Project to which the Time entry is linked to.
    """

    task = fields.MappingField(Task, 'tid', premium=True)
    """
    Task to which the Time entry is linked to.

    (Available only for Premium workspaces)
    """

    billable = fields.BooleanField(default=False, premium=True)
    """
    If available to be billed. (Default: False)

    (Available only for Premium workspaces)
    """

    start = TimeEntryDateTimeField(required=True)
    """
    DateTime of start of the time entry. (Required)
    """

    stop = TimeEntryDateTimeField()
    """
    DateTime of end of the time entry.
    """

    duration = fields.PropertyField(get_duration,
                                    set_duration,
                                    formatter=format_duration)
    """
    Dynamic field of entry's duration in seconds.

    If the time entry is currently running, the duration attribute contains a negative value,
    denoting the start of the time entry in seconds since epoch (Jan 1 1970). The correct duration can be
    calculated as current_time + duration, where current_time is the current time in seconds since epoch.
    """

    created_with = fields.StringField(required=True,
                                      default='TogglCLI',
                                      read=False)
    """
    Information who created the time entry.
    """

    tags = fields.SetField()
    """
    Set of tags associated with the time entry.
    """

    objects = TimeEntrySet()

    def __init__(self, start, stop=None, duration=None, **kwargs):
        if stop is None and duration is None:
            raise ValueError(
                'You can create only finished time entries through this way! '
                'You must supply either \'stop\' or \'duration\' parameter!')

        super().__init__(start=start, stop=stop, duration=duration, **kwargs)

    @classmethod
    def get_url(cls):
        return 'time_entries'

    def to_dict(self, serialized=False, changes_only=False):
        # Enforcing serialize duration when start or stop changes
        if changes_only and (self.__change_dict__.get('start')
                             or self.__change_dict__.get('stop')):
            self.__change_dict__['duration'] = None

        return super().to_dict(serialized=serialized,
                               changes_only=changes_only)

    @classmethod
    def start_and_save(
        cls,
        start=None,
        config=None,
        **kwargs
    ):  # type: (pendulum.DateTime, utils.Config, **typing.Any) -> TimeEntry
        """
        Creates a new running entry.

        If there is another running time entry in the time of calling this method, then the running entry is stopped.
        This is handled by Toggl's backend.

        :param start: The DateTime object representing start of the new TimeEntry. If None than current time is used.
        :param config:
        :param kwargs: Other parameters for creating the new TimeEntry
        :return: New running TimeEntry
        """
        config = config or utils.Config.factory()

        if start is None:
            start = pendulum.now(config.timezone)

        if 'stop' in kwargs or 'duration' in kwargs:
            raise RuntimeError(
                'With start_and_save() method you can not create finished entries!'
            )

        instance = cls.__new__(cls)
        instance.__change_dict__ = {}
        instance.is_running = True
        instance._config = config
        instance.start = start

        for key, value in kwargs.items():
            setattr(instance, key, value)

        instance.save()

        return instance

    def stop_and_save(self=None, stop=None):
        """
        Stops running the entry. It has to be running entry.

        :param stop: DateTime which should be set as stop time. If None, then current time is used.
        :return: Self
        """
        if self is None:
            # noinspection PyMethodFirstArgAssignment
            self = TimeEntry.objects.current()
            if self is None:
                raise exceptions.TogglValidationException(
                    'There is no running entry to be stoped!')

        if not self.is_running:
            raise exceptions.TogglValidationException(
                'You can\'t stop not running entry!')

        config = self._config or utils.Config.factory()

        if stop is None:
            stop = pendulum.now(config.timezone)

        self.stop = stop
        self.is_running = False
        self.save(config=config)

        return self

    def continue_and_save(self, start=None):
        """
        Creates new time entry with same description as the self entry and starts running it.

        :param start: The DateTime object representing start of the new TimeEntry. If None than current time is used.
        :return: The new TimeEntry.
        """
        if self.is_running:
            logger.warning(
                'Trying to continue time entry {} which is already running!'.
                format(self))

        config = self._config or utils.Config.factory()

        if start is None:
            start = pendulum.now(config.timezone)

        new_entry = copy(self)
        new_entry.start = start
        new_entry.stop = None
        new_entry.is_running = True

        new_entry.save(config=config)

        return new_entry

    def __str__(self):
        return '{} (#{})'.format(getattr(self, 'description', ''), self.id)
Example #3
0
class SetEntity(base.TogglEntity):
    field = fields.SetField()  # type: set
Example #4
0
class EvaluateConditionsEntity(base.TogglEntity):
    string = fields.StringField()
    integer = fields.IntegerField()
    boolean = fields.BooleanField()
    set = fields.SetField()