__all__ = [
'Task',
]
import datetime
import functools
import json
import logging
from typing import Optional
from .. import constants
from ..enums import (
TaskAcceptance, TaskHistory, TaskMode, TaskMultipleRecipients,
TaskOwnership, TaskState, TaskStatus
)
from .message_base import MessageBase
from ..structures.recurrence_pattern import RecurrencePattern
from ..utils import unsignedToSignedInt
logger = logging.getLogger(__name__)
logger.addHandler(logging.NullHandler())
class Task(MessageBase):
"""
Class used for parsing task files.
"""
def getJson(self) -> str:
status = {
TaskStatus.NOT_STARTED: 'Not Started',
TaskStatus.IN_PROGRESS: 'In Progress',
TaskStatus.COMPLETE: 'Completed',
TaskStatus.WAITING_ON_OTHER: 'Waiting on someone else',
TaskStatus.DEFERRED: 'Deferred',
None: None,
}[self.taskStatus]
return json.dumps({
'subject': self.subject,
'status': status,
'percentComplete': f'{self.percentComplete*100:.0f}%',
'dateCompleted': self.taskDateCompleted.__format__(self.dateFormat) if self.taskDateCompleted else None,
'totalWork': f'{self.taskEstimatedEffort or 0} minutes',
'actualWork': f'{self.taskActualEffort or 0} minutes',
'owner': self.taskOwner,
'importance': self.importanceString,
})
@property
def headerFormatProperties(self) -> constants.HEADER_FORMAT_TYPE:
status = {
TaskStatus.NOT_STARTED: 'Not Started',
TaskStatus.IN_PROGRESS: 'In Progress',
TaskStatus.COMPLETE: 'Completed',
TaskStatus.WAITING_ON_OTHER: 'Waiting on someone else',
TaskStatus.DEFERRED: 'Deferred',
None: None,
}[self.taskStatus]
return {
'-basic info-': {
'Subject': self.subject,
},
'-status-': {
'Status': status,
'Percent Complete': f'{self.percentComplete*100:.0f}%',
'Date Completed': self.taskDateCompleted.__format__(self.dateFormat) if self.taskDateCompleted else None,
},
'-work-': {
'Total Work': f'{self.taskEstimatedEffort or 0} minutes',
'Actual Work': f'{self.taskActualEffort or 0} minutes',
},
'-owner-': {
'Owner': self.taskOwner,
},
'-importance-': {
'Importance': self.importanceString,
},
}
@functools.cached_property
def percentComplete(self) -> float:
"""
Indicates whether a time-flagged Message object is complete.
:returns: A percentage in decimal form. 1.0 indicates it is complete.
"""
return self.getNamedProp('8102', constants.ps.PSETID_TASK, 0.0)
@functools.cached_property
def taskAcceptanceState(self) -> Optional[TaskAcceptance]:
"""
Indicates the acceptance state of the task.
"""
return self.getNamedAs('812A', constants.ps.PSETID_TASK, TaskAcceptance)
@functools.cached_property
def taskAccepted(self) -> bool:
"""
Indicates whether a task assignee has replied to a tesk request for this
task object.
Does not indicate if it was accepted or rejected.
"""
return bool(self.getNamedProp('8108', constants.ps.PSETID_TASK))
@functools.cached_property
def taskActualEffort(self) -> Optional[int]:
"""
Indicates the number of minutes that the user actually spent working on
a task.
"""
return self.getNamedProp('8110', constants.ps.PSETID_TASK)
@functools.cached_property
def taskAssigner(self) -> Optional[str]:
"""
Specifies the name of the user that last assigned the task.
"""
return self.getNamedProp('8121', constants.ps.PSETID_TASK)
@functools.cached_property
def taskAssigners(self) -> Optional[bytes]:
"""
A stack of entries, each representing a task assigner.
The most recent task assigner (that is, the top) appears at the bottom.
The documentation on this is weird, so I don't know how to parse it.
"""
return self.getNamedProp('8117', constants.ps.PSETID_TASK)
@functools.cached_property
def taskComplete(self) -> bool:
"""
Indicates if the task is complete.
"""
return bool(self.getNamedProp('811C', constants.ps.PSETID_TASK))
@functools.cached_property
def taskCustomFlags(self) -> Optional[int]:
"""
Custom flags set on the task.
"""
return self.getNamedProp('8139', constants.ps.PSETID_TASK)
@functools.cached_property
def taskDateCompleted(self) -> Optional[datetime.datetime]:
"""
The date when the user completed work on the task.
"""
return self.getNamedProp('810F', constants.ps.PSETID_TASK)
@functools.cached_property
def taskDeadOccurrence(self) -> bool:
"""
Indicates whether a new recurring task remains to be generated.
Set to ``False`` on a new Task object and ``True`` when the client
generates the last recurring task.
"""
return bool(self.getNamedProp('8109', constants.ps.PSETID_TASK))
@functools.cached_property
def taskDueDate(self) -> Optional[datetime.datetime]:
"""
Specifies the date by which the user expects work on the task to be
complete.
"""
return self.getNamedProp('8105', constants.ps.PSETID_TASK)
@functools.cached_property
def taskEstimatedEffort(self) -> Optional[int]:
"""
Indicates the number of minutes that the user expects to work on a task.
"""
return self.getNamedProp('8111', constants.ps.PSETID_TASK)
@functools.cached_property
def taskFCreator(self) -> bool:
"""
Indicates that the task object was originally created by the action of
the current user or user agent instead of by the processing of a task
request.
"""
return bool(self.getNamedProp('811E', constants.ps.PSETID_TASK))
@functools.cached_property
def taskFFixOffline(self) -> bool:
"""
Indicates whether the value of the taskOwner property is correct.
"""
return bool(self.getNamedProp('812C', constants.ps.PSETID_TASK))
@functools.cached_property
def taskFRecurring(self) -> bool:
"""
Indicates whether the task includes a recurrence pattern.
"""
return bool(self.getNamedProp('8126', constants.ps.PSETID_TASK))
@functools.cached_property
def taskGlobalID(self) -> Optional[bytes]:
"""
Specifies a unique GUID for this task, used to locate an existing task
upon receipt of a task response or task update.
"""
return self.getNamedProp('8519', constants.ps.PSETID_COMMON)
@functools.cached_property
def taskHistory(self) -> Optional[TaskHistory]:
"""
Indicates the type of change that was last made to the Task object.
"""
return self.getNamedAs('811A', constants.ps.PSETID_TASK, TaskHistory)
@functools.cached_property
def taskLastDelegate(self) -> Optional[str]:
"""
Contains the name of the user who most recently assigned the task, or
the user to whom it was most recently assigned.
"""
return self.getNamedProp('8125', constants.ps.PSETID_TASK)
@functools.cached_property
def taskLastUpdate(self) -> Optional[datetime.datetime]:
"""
The date and time of the most recent change made to the task object.
"""
return self.getNamedProp('8115', constants.ps.PSETID_TASK)
@functools.cached_property
def taskLastUser(self) -> Optional[str]:
"""
Contains the name of the most recent user to have been the owner of the
task.
"""
return self.getNamedProp('8122', constants.ps.PSETID_TASK)
@functools.cached_property
def taskMode(self) -> Optional[TaskMode]:
"""
Used in a task communication.
Should be 0 (UNASSIGNED) on task objects.
"""
return self.getNamedAs('8518', constants.ps.PSETID_COMMON, TaskMode)
@functools.cached_property
def taskMultipleRecipients(self) -> Optional[TaskMultipleRecipients]:
"""
Returns a union of flags that specify optimization hints about the
recipients of a Task object.
"""
return self.getNamedAs('8120', constants.ps.PSETID_TASK, TaskMultipleRecipients)
@functools.cached_property
def taskNoCompute(self) -> Optional[bool]:
"""
This value is not used and has no impact on a Task, but is provided for
completeness.
"""
return self.getNamedProp('8124', constants.ps.PSETID_TASK)
@functools.cached_property
def taskOrdinal(self) -> Optional[int]:
"""
Specifies a number that aids custom sorting of Task objects.
"""
return self.getNamedAs('8123', constants.ps.PSETID_TASK, unsignedToSignedInt)
@functools.cached_property
def taskOwner(self) -> Optional[str]:
"""
Contains the name of the owner of the task.
"""
return self.getNamedProp('811F', constants.ps.PSETID_TASK)
@functools.cached_property
def taskOwnership(self) -> Optional[TaskOwnership]:
"""
Contains the name of the owner of the task.
"""
return self.getNamedAs('8129', constants.ps.PSETID_TASK, TaskOwnership)
@functools.cached_property
def taskRecurrence(self) -> Optional[RecurrencePattern]:
"""
Contains a RecurrencePattern structure that provides information about
recurring tasks.
"""
return self.getNamedAs('8116', constants.ps.PSETID_TASK, RecurrencePattern)
@functools.cached_property
def taskResetReminder(self) -> bool:
"""
Indicates whether future recurring tasks need reminders.
"""
return bool(self.getNamedProp('8107', constants.ps.PSETID_TASK))
@functools.cached_property
def taskRole(self) -> Optional[str]:
"""
This value is not used and has no impact on a Task, but is provided for
completeness.
"""
return self.getNamedProp('8127', constants.ps.PSETID_TASK)
@functools.cached_property
def taskStartDate(self) -> Optional[datetime.datetime]:
"""
Specifies the date on which the user expects work on the task to begin.
"""
return self.getNamedProp('8104', constants.ps.PSETID_TASK)
@functools.cached_property
def taskState(self) -> Optional[TaskState]:
"""
Indicates the current assignment state of the Task object.
"""
return self.getNamedAs('8113', constants.ps.PSETID_TASK, TaskState)
@functools.cached_property
def taskStatus(self) -> Optional[TaskStatus]:
"""
The completion status of a task.
"""
return self.getNamedAs('8101', constants.ps.PSETID_TASK, TaskStatus)
@functools.cached_property
def taskStatusOnComplete(self) -> bool:
"""
Indicates whether the task assignee has been requested to send an email
message upon completion of the assigned task.
"""
return bool(self.getNamedProp('8119', constants.ps.PSETID_TASK))
@functools.cached_property
def taskUpdates(self) -> bool:
"""
Indicates whether the task assignee has been requested to send a task
update when the assigned Task object changes.
"""
return bool(self.getNamedProp('811B', constants.ps.PSETID_TASK))
@functools.cached_property
def taskVersion(self) -> Optional[int]:
"""
Indicates which copy is the latest update of a Task object.
"""
return self.getNamedProp('8112', constants.ps.PSETID_TASK)
@functools.cached_property
def teamTask(self) -> Optional[bool]:
"""
This value is not used and has no impact on a Task, but is provided for
completeness.
"""
return self.getNamedProp('8103', constants.ps.PSETID_TASK)