Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Changed

- Use `dataclasses_json` for object mapping
- Use `dataclass-wizard` for object mapping

### Fixes

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ dependencies = [

### Supported Python Versions

Python 3.13 is fully supported and tested, and while it should work with other Python 3 versions, we do not test for them.
While we only actively test under Python 3.13, we strive to support all versions from Python 3.9 and above.

### Usage

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ classifiers = [
"Topic :: Software Development :: Libraries :: Python Modules",
]

dependencies = ["requests>=2.32.3,<3", "dataclasses-json>=0.6.7,<0.7"]
dependencies = ["requests>=2.32.3,<3", "dataclass-wizard>=0.35.0,<1.0"]

[project.urls]
Homepage = "https://github.com/Doist/todoist-api-python"
Expand Down
92 changes: 60 additions & 32 deletions todoist_api_python/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@
from dataclasses import dataclass, field
from typing import Any, Literal

from dataclasses_json import DataClassJsonMixin
from dataclass_wizard import JSONPyWizard

from todoist_api_python.utils import get_url_for_task

VIEW_STYLE = Literal["list", "board"]


@dataclass
class Project(DataClassJsonMixin):
class Project(JSONPyWizard):
class _(JSONPyWizard.Meta): # noqa:N801
v1 = True

color: str
comment_count: int
id: str
Expand All @@ -28,40 +31,38 @@ class Project(DataClassJsonMixin):


@dataclass
class Section(DataClassJsonMixin):
class Section(JSONPyWizard):
class _(JSONPyWizard.Meta): # noqa:N801
v1 = True

id: str
name: str
order: int
project_id: str


@dataclass
class Due(DataClassJsonMixin):
class Due(JSONPyWizard):
class _(JSONPyWizard.Meta): # noqa:N801
v1 = True

date: str
is_recurring: bool
string: str

datetime: str | None = None
timezone: str | None = None

@classmethod
def from_quick_add_response(cls, obj: dict[str, Any]) -> Due | None:
due = obj.get("due")

if not due:
return None

timezone = due.get("timezone")
datetime: str | None = due["date"] if timezone is not None else None

due["datetime"] = datetime
due["timezone"] = timezone

return cls.from_dict(due)
def __post_init__(self) -> None:
if not self.datetime and (self.date and self.timezone):
self.datetime = self.date


@dataclass
class Task(DataClassJsonMixin):
class Task(JSONPyWizard):
class _(JSONPyWizard.Meta): # noqa:N801
v1 = True

assignee_id: str | None
assigner_id: str | None
comment_count: int
Expand Down Expand Up @@ -91,9 +92,6 @@ def __post_init__(self) -> None:
@classmethod
def from_quick_add_response(cls, obj: dict[str, Any]) -> Task:
obj_copy = obj.copy()
obj_copy["due"] = (
Due.from_quick_add_response(obj) if obj.get("due") is not None else None
)
obj_copy["comment_count"] = 0
obj_copy["is_completed"] = False
obj_copy["created_at"] = obj_copy.pop("added_at", None)
Expand All @@ -106,7 +104,10 @@ def from_quick_add_response(cls, obj: dict[str, Any]) -> Task:


@dataclass
class QuickAddResult(DataClassJsonMixin):
class QuickAddResult(JSONPyWizard):
class _(JSONPyWizard.Meta): # noqa:N801
v1 = True

task: Task

resolved_project_name: str | None = None
Expand Down Expand Up @@ -145,14 +146,20 @@ def from_quick_add_response(cls, obj: dict[str, Any]) -> QuickAddResult:


@dataclass
class Collaborator(DataClassJsonMixin):
class Collaborator(JSONPyWizard):
class _(JSONPyWizard.Meta): # noqa:N801
v1 = True

id: str
email: str
name: str


@dataclass
class Attachment(DataClassJsonMixin):
class Attachment(JSONPyWizard):
class _(JSONPyWizard.Meta): # noqa:N801
v1 = True

resource_type: str | None = None

file_name: str | None = None
Expand All @@ -171,7 +178,10 @@ class Attachment(DataClassJsonMixin):


@dataclass
class Comment(DataClassJsonMixin):
class Comment(JSONPyWizard):
class _(JSONPyWizard.Meta): # noqa:N801
v1 = True

content: str
id: str
posted_at: str
Expand All @@ -181,7 +191,10 @@ class Comment(DataClassJsonMixin):


@dataclass
class Label(DataClassJsonMixin):
class Label(JSONPyWizard):
class _(JSONPyWizard.Meta): # noqa:N801
v1 = True

id: str
name: str
color: str
Expand All @@ -190,13 +203,19 @@ class Label(DataClassJsonMixin):


@dataclass
class AuthResult(DataClassJsonMixin):
class AuthResult(JSONPyWizard):
class _(JSONPyWizard.Meta): # noqa:N801
v1 = True

access_token: str
state: str | None


@dataclass
class Item(DataClassJsonMixin):
class Item(JSONPyWizard):
class _(JSONPyWizard.Meta): # noqa:N801
v1 = True

id: str
user_id: str
project_id: str
Expand All @@ -221,13 +240,19 @@ class Item(DataClassJsonMixin):


@dataclass
class ItemCompletedInfo(DataClassJsonMixin):
class ItemCompletedInfo(JSONPyWizard):
class _(JSONPyWizard.Meta): # noqa:N801
v1 = True

item_id: str
completed_items: int


@dataclass
class CompletedItems(DataClassJsonMixin):
class CompletedItems(JSONPyWizard):
class _(JSONPyWizard.Meta): # noqa:N801
v1 = True

items: list[Item]
total: int
completed_info: list[ItemCompletedInfo]
Expand All @@ -236,6 +261,9 @@ class CompletedItems(DataClassJsonMixin):


@dataclass
class Duration(DataClassJsonMixin):
class Duration(JSONPyWizard):
class _(JSONPyWizard.Meta): # noqa:N801
v1 = True

amount: int
unit: str
41 changes: 6 additions & 35 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.