You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							360 lines
						
					
					
						
							9.9 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							360 lines
						
					
					
						
							9.9 KiB
						
					
					
				
								from __future__ import annotations
							 | 
						|
								
							 | 
						|
								from typing import List, Literal
							 | 
						|
								
							 | 
						|
								import attr
							 | 
						|
								
							 | 
						|
								from ..todoist_api_python.utils import get_url_for_task
							 | 
						|
								
							 | 
						|
								VIEW_STYLE = Literal["list", "board"]
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								@attr.s
							 | 
						|
								class Project(object):
							 | 
						|
								    color: str = attr.ib()
							 | 
						|
								    comment_count: int = attr.ib()
							 | 
						|
								    id: str = attr.ib()
							 | 
						|
								    is_favorite: bool = attr.ib()
							 | 
						|
								    is_inbox_project: bool = attr.ib()
							 | 
						|
								    is_shared: bool = attr.ib()
							 | 
						|
								    is_team_inbox: bool = attr.ib()
							 | 
						|
								    name: str = attr.ib()
							 | 
						|
								    order: int = attr.ib()
							 | 
						|
								    parent_id: str | None = attr.ib()
							 | 
						|
								    url: str = attr.ib()
							 | 
						|
								    view_style: VIEW_STYLE = attr.ib()
							 | 
						|
								
							 | 
						|
								    @classmethod
							 | 
						|
								    def from_dict(cls, obj):
							 | 
						|
								        return cls(
							 | 
						|
								            color=obj["color"],
							 | 
						|
								            comment_count=obj["comment_count"],
							 | 
						|
								            id=obj["id"],
							 | 
						|
								            is_favorite=obj["is_favorite"],
							 | 
						|
								            is_inbox_project=obj.get("is_inbox_project"),
							 | 
						|
								            is_shared=obj["is_shared"],
							 | 
						|
								            is_team_inbox=obj.get("is_team_inbox"),
							 | 
						|
								            name=obj["name"],
							 | 
						|
								            order=obj.get("order"),
							 | 
						|
								            parent_id=obj.get("parent_id"),
							 | 
						|
								            url=obj["url"],
							 | 
						|
								            view_style=obj["view_style"],
							 | 
						|
								        )
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								@attr.s
							 | 
						|
								class Section(object):
							 | 
						|
								    id: str = attr.ib()
							 | 
						|
								    name: str = attr.ib()
							 | 
						|
								    order: int = attr.ib()
							 | 
						|
								    project_id: str = attr.ib()
							 | 
						|
								
							 | 
						|
								    @classmethod
							 | 
						|
								    def from_dict(cls, obj):
							 | 
						|
								        return cls(
							 | 
						|
								            id=obj["id"],
							 | 
						|
								            name=obj["name"],
							 | 
						|
								            order=obj["order"],
							 | 
						|
								            project_id=obj["project_id"],
							 | 
						|
								        )
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								@attr.s
							 | 
						|
								class Due(object):
							 | 
						|
								    date: str = attr.ib()
							 | 
						|
								    is_recurring: bool = attr.ib()
							 | 
						|
								    string: str = attr.ib()
							 | 
						|
								
							 | 
						|
								    datetime: str | None = attr.ib(default=None)
							 | 
						|
								    timezone: str | None = attr.ib(default=None)
							 | 
						|
								
							 | 
						|
								    @classmethod
							 | 
						|
								    def from_dict(cls, obj):
							 | 
						|
								        return cls(
							 | 
						|
								            date=obj["date"],
							 | 
						|
								            is_recurring=obj["is_recurring"],
							 | 
						|
								            string=obj["string"],
							 | 
						|
								            datetime=obj.get("datetime"),
							 | 
						|
								            timezone=obj.get("timezone"),
							 | 
						|
								        )
							 | 
						|
								
							 | 
						|
								    def to_dict(self):
							 | 
						|
								        return {
							 | 
						|
								            "date": self.date,
							 | 
						|
								            "is_recurring": self.is_recurring,
							 | 
						|
								            "string": self.string,
							 | 
						|
								            "datetime": self.datetime,
							 | 
						|
								            "timezone": self.timezone,
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								    @classmethod
							 | 
						|
								    def from_quick_add_response(cls, obj):
							 | 
						|
								        due = obj.get("due")
							 | 
						|
								
							 | 
						|
								        if not due:
							 | 
						|
								            return None
							 | 
						|
								
							 | 
						|
								        timezone = due.get("timezone")
							 | 
						|
								
							 | 
						|
								        datetime: str | None = None
							 | 
						|
								
							 | 
						|
								        if timezone:
							 | 
						|
								            datetime = due["date"]
							 | 
						|
								
							 | 
						|
								        return cls(
							 | 
						|
								            date=due["date"],
							 | 
						|
								            is_recurring=due["is_recurring"],
							 | 
						|
								            string=due["string"],
							 | 
						|
								            datetime=datetime,
							 | 
						|
								            timezone=timezone,
							 | 
						|
								        )
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								@attr.s
							 | 
						|
								class Task(object):
							 | 
						|
								    assignee_id: str | None = attr.ib()
							 | 
						|
								    assigner_id: str | None = attr.ib()
							 | 
						|
								    comment_count: int = attr.ib()
							 | 
						|
								    is_completed: bool = attr.ib()
							 | 
						|
								    content: str = attr.ib()
							 | 
						|
								    created_at: str = attr.ib()
							 | 
						|
								    creator_id: str = attr.ib()
							 | 
						|
								    description: str = attr.ib()
							 | 
						|
								    due: Due | None = attr.ib()
							 | 
						|
								    id: str = attr.ib()
							 | 
						|
								    labels: List[str] = attr.ib()
							 | 
						|
								    order: int = attr.ib()
							 | 
						|
								    parent_id: str | None = attr.ib()
							 | 
						|
								    priority: int = attr.ib()
							 | 
						|
								    project_id: str = attr.ib()
							 | 
						|
								    section_id: str | None = attr.ib()
							 | 
						|
								    url: str = attr.ib()
							 | 
						|
								
							 | 
						|
								    sync_id: str | None = attr.ib(default=None)
							 | 
						|
								
							 | 
						|
								    @classmethod
							 | 
						|
								    def from_dict(cls, obj):
							 | 
						|
								        due: Due | None = None
							 | 
						|
								
							 | 
						|
								        if obj.get("due"):
							 | 
						|
								            due = Due.from_dict(obj["due"])
							 | 
						|
								
							 | 
						|
								        return cls(
							 | 
						|
								            assignee_id=obj.get("assignee_id"),
							 | 
						|
								            assigner_id=obj.get("assigner_id"),
							 | 
						|
								            comment_count=obj["comment_count"],
							 | 
						|
								            is_completed=obj["is_completed"],
							 | 
						|
								            content=obj["content"],
							 | 
						|
								            created_at=obj["created_at"],
							 | 
						|
								            creator_id=obj["creator_id"],
							 | 
						|
								            description=obj["description"],
							 | 
						|
								            due=due,
							 | 
						|
								            id=obj["id"],
							 | 
						|
								            labels=obj.get("labels"),
							 | 
						|
								            order=obj.get("order"),
							 | 
						|
								            parent_id=obj.get("parent_id"),
							 | 
						|
								            priority=obj["priority"],
							 | 
						|
								            project_id=obj["project_id"],
							 | 
						|
								            section_id=obj["section_id"],
							 | 
						|
								            url=obj["url"],
							 | 
						|
								        )
							 | 
						|
								
							 | 
						|
								    def to_dict(self):
							 | 
						|
								        due: dict | None = None
							 | 
						|
								
							 | 
						|
								        if self.due:
							 | 
						|
								            due = self.due.to_dict()
							 | 
						|
								
							 | 
						|
								        return {
							 | 
						|
								            "assignee_id": self.assignee_id,
							 | 
						|
								            "assigner_id": self.assigner_id,
							 | 
						|
								            "comment_count": self.comment_count,
							 | 
						|
								            "is_completed": self.is_completed,
							 | 
						|
								            "content": self.content,
							 | 
						|
								            "created_at": self.created_at,
							 | 
						|
								            "creator_id": self.creator_id,
							 | 
						|
								            "description": self.description,
							 | 
						|
								            "due": due,
							 | 
						|
								            "id": self.id,
							 | 
						|
								            "labels": self.labels,
							 | 
						|
								            "order": self.order,
							 | 
						|
								            "parent_id": self.parent_id,
							 | 
						|
								            "priority": self.priority,
							 | 
						|
								            "project_id": self.project_id,
							 | 
						|
								            "section_id": self.section_id,
							 | 
						|
								            "sync_id": self.sync_id,
							 | 
						|
								            "url": self.url,
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								    @classmethod
							 | 
						|
								    def from_quick_add_response(cls, obj):
							 | 
						|
								        due: Due | None = None
							 | 
						|
								
							 | 
						|
								        if obj.get("due"):
							 | 
						|
								            due = Due.from_quick_add_response(obj)
							 | 
						|
								
							 | 
						|
								        return cls(
							 | 
						|
								            assignee_id=obj.get("responsible_uid"),
							 | 
						|
								            assigner_id=obj.get("assigned_by_uid"),
							 | 
						|
								            comment_count=0,
							 | 
						|
								            is_completed=False,
							 | 
						|
								            content=obj["content"],
							 | 
						|
								            created_at=obj["added_at"],
							 | 
						|
								            creator_id=obj["added_by_uid"],
							 | 
						|
								            description=obj["description"],
							 | 
						|
								            due=due,
							 | 
						|
								            id=obj["id"],
							 | 
						|
								            labels=obj["labels"],
							 | 
						|
								            order=obj["child_order"],
							 | 
						|
								            parent_id=obj["parent_id"] or None,
							 | 
						|
								            priority=obj["priority"],
							 | 
						|
								            project_id=obj["project_id"],
							 | 
						|
								            section_id=obj["section_id"] or None,
							 | 
						|
								            sync_id=obj["sync_id"],
							 | 
						|
								            url=get_url_for_task(obj["id"], obj["sync_id"]),
							 | 
						|
								        )
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								@attr.s
							 | 
						|
								class QuickAddResult:
							 | 
						|
								    task: Task = attr.ib()
							 | 
						|
								
							 | 
						|
								    resolved_project_name: str | None = attr.ib(default=None)
							 | 
						|
								    resolved_assignee_name: str | None = attr.ib(default=None)
							 | 
						|
								    resolved_label_names: List[str] | None = attr.ib(default=None)
							 | 
						|
								    resolved_section_name: str | None = attr.ib(default=None)
							 | 
						|
								
							 | 
						|
								    @classmethod
							 | 
						|
								    def from_quick_add_response(cls, obj):
							 | 
						|
								        project_data = obj["meta"].get("project", {})
							 | 
						|
								        assignee_data = obj["meta"].get("assignee", {})
							 | 
						|
								        section_data = obj["meta"].get("section", {})
							 | 
						|
								
							 | 
						|
								        resolved_project_name = None
							 | 
						|
								        resolved_assignee_name = None
							 | 
						|
								        resolved_section_name = None
							 | 
						|
								
							 | 
						|
								        if project_data and len(project_data) == 2:
							 | 
						|
								            resolved_project_name = obj["meta"]["project"][1]
							 | 
						|
								
							 | 
						|
								        if assignee_data and len(assignee_data) == 2:
							 | 
						|
								            resolved_assignee_name = obj["meta"]["assignee"][1]
							 | 
						|
								
							 | 
						|
								        if section_data and len(section_data) == 2:
							 | 
						|
								            resolved_section_name = obj["meta"]["section"][1]
							 | 
						|
								
							 | 
						|
								        return cls(
							 | 
						|
								            task=Task.from_quick_add_response(obj),
							 | 
						|
								            resolved_project_name=resolved_project_name,
							 | 
						|
								            resolved_assignee_name=resolved_assignee_name,
							 | 
						|
								            resolved_label_names=list(obj["meta"]["labels"].values()),
							 | 
						|
								            resolved_section_name=resolved_section_name,
							 | 
						|
								        )
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								@attr.s
							 | 
						|
								class Collaborator(object):
							 | 
						|
								    id: str = attr.ib()
							 | 
						|
								    email: str = attr.ib()
							 | 
						|
								    name: str = attr.ib()
							 | 
						|
								
							 | 
						|
								    @classmethod
							 | 
						|
								    def from_dict(cls, obj):
							 | 
						|
								        return cls(
							 | 
						|
								            id=obj["id"],
							 | 
						|
								            email=obj["email"],
							 | 
						|
								            name=obj["name"],
							 | 
						|
								        )
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								@attr.s
							 | 
						|
								class Attachment(object):
							 | 
						|
								    resource_type: str | None = attr.ib(default=None)
							 | 
						|
								
							 | 
						|
								    file_name: str | None = attr.ib(default=None)
							 | 
						|
								    file_size: int | None = attr.ib(default=None)
							 | 
						|
								    file_type: str | None = attr.ib(default=None)
							 | 
						|
								    file_url: str | None = attr.ib(default=None)
							 | 
						|
								    file_duration: int | None = attr.ib(default=None)
							 | 
						|
								    upload_state: str | None = attr.ib(default=None)
							 | 
						|
								
							 | 
						|
								    image: str | None = attr.ib(default=None)
							 | 
						|
								    image_width: int | None = attr.ib(default=None)
							 | 
						|
								    image_height: int | None = attr.ib(default=None)
							 | 
						|
								
							 | 
						|
								    url: str | None = attr.ib(default=None)
							 | 
						|
								    title: str | None = attr.ib(default=None)
							 | 
						|
								
							 | 
						|
								    @classmethod
							 | 
						|
								    def from_dict(cls, obj):
							 | 
						|
								        return cls(
							 | 
						|
								            resource_type=obj.get("resource_type"),
							 | 
						|
								            file_name=obj.get("file_name"),
							 | 
						|
								            file_size=obj.get("file_size"),
							 | 
						|
								            file_type=obj.get("file_type"),
							 | 
						|
								            file_url=obj.get("file_url"),
							 | 
						|
								            upload_state=obj.get("upload_state"),
							 | 
						|
								            image=obj.get("image"),
							 | 
						|
								            image_width=obj.get("image_width"),
							 | 
						|
								            image_height=obj.get("image_height"),
							 | 
						|
								            url=obj.get("url"),
							 | 
						|
								            title=obj.get("title"),
							 | 
						|
								        )
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								@attr.s
							 | 
						|
								class Comment(object):
							 | 
						|
								    attachment: Attachment | None = attr.ib()
							 | 
						|
								    content: str = attr.ib()
							 | 
						|
								    id: str = attr.ib()
							 | 
						|
								    posted_at: str = attr.ib()
							 | 
						|
								    project_id: str | None = attr.ib()
							 | 
						|
								    task_id: str | None = attr.ib()
							 | 
						|
								
							 | 
						|
								    @classmethod
							 | 
						|
								    def from_dict(cls, obj):
							 | 
						|
								        attachment: Attachment | None = None
							 | 
						|
								
							 | 
						|
								        if "attachment" in obj and obj["attachment"] is not None:
							 | 
						|
								            attachment = Attachment.from_dict(obj["attachment"])
							 | 
						|
								
							 | 
						|
								        return cls(
							 | 
						|
								            attachment=attachment,
							 | 
						|
								            content=obj["content"],
							 | 
						|
								            id=obj["id"],
							 | 
						|
								            posted_at=obj["posted_at"],
							 | 
						|
								            project_id=obj.get("project_id"),
							 | 
						|
								            task_id=obj.get("task_id"),
							 | 
						|
								        )
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								@attr.s
							 | 
						|
								class Label:
							 | 
						|
								    id: str = attr.ib()
							 | 
						|
								    name: str = attr.ib()
							 | 
						|
								    color: str = attr.ib()
							 | 
						|
								    order: int = attr.ib()
							 | 
						|
								    is_favorite: bool = attr.ib()
							 | 
						|
								
							 | 
						|
								    @classmethod
							 | 
						|
								    def from_dict(cls, obj):
							 | 
						|
								        return cls(
							 | 
						|
								            id=obj["id"],
							 | 
						|
								            name=obj["name"],
							 | 
						|
								            color=obj["color"],
							 | 
						|
								            order=obj["order"],
							 | 
						|
								            is_favorite=obj["is_favorite"],
							 | 
						|
								        )
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								@attr.s
							 | 
						|
								class AuthResult:
							 | 
						|
								    access_token: str = attr.ib()
							 | 
						|
								    state: str = attr.ib()
							 | 
						|
								
							 | 
						|
								    @classmethod
							 | 
						|
								    def from_dict(cls, obj):
							 | 
						|
								        return cls(
							 | 
						|
								            access_token=obj["access_token"],
							 | 
						|
								            state=obj["state"],
							 | 
						|
								        )
							 | 
						|
								
							 |