From cd74db12186d51428b5b29cd0cf8b0ce912929d0 Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 2 Nov 2026 10:48:49 +0100 Subject: [PATCH] fix: load projects with unknown view styles `Project.view_style` was typed as the `ViewStyle` literal, so any value the SDK didn't list (e.g. the upcoming `table` layout) raised `ParseError` and failed the whole load. Read it as `str` and keep the value as sent. The `ViewStyle` names and request-side validation are unchanged. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 4 ++++ tests/test_models.py | 12 ++++++++++++ todoist_api_python/models.py | 3 ++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c552438..87df1a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **Breaking**: `update_section` now accepts only keyword arguments after `section_id`; any one of `name`, `order`, or `collapsed` can be updated in the same call. - **Breaking**: `add_label` and `update_label` now accept `order` instead of `item_order` for label ordering. (#247) +### Fixed + +- Loading a project no longer fails when its `view_style` is one the SDK doesn't know yet; `Project.view_style` is now typed as `str` and keeps the value as sent. + ## [3.2.1] - 2026-01-22 ### Fixed diff --git a/tests/test_models.py b/tests/test_models.py index 3ec24ba..ea6baf4 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,5 +1,7 @@ from __future__ import annotations +import pytest + from tests.data.test_defaults import ( DEFAULT_ATTACHMENT_RESPONSE, DEFAULT_COLLABORATOR_RESPONSE, @@ -76,6 +78,16 @@ def test_project_from_dict() -> None: assert project.updated_at == parse_datetime(str(sample_data["updated_at"])) +@pytest.mark.parametrize("view_style", ["table", "some_future_view_style"]) +def test_project_from_dict_with_unknown_view_style(view_style: str) -> None: + sample_data = dict(DEFAULT_PROJECT_RESPONSE) + sample_data["view_style"] = view_style + + project = Project.from_dict(sample_data) + + assert project.view_style == view_style + + def test_project_url() -> None: inbox = Project.from_dict(dict(DEFAULT_PROJECT_RESPONSE)) assert inbox.url == "https://app.todoist.com/app/inbox" diff --git a/todoist_api_python/models.py b/todoist_api_python/models.py index 55364f7..4486bb6 100644 --- a/todoist_api_python/models.py +++ b/todoist_api_python/models.py @@ -35,7 +35,8 @@ class _(JSONPyWizard.Meta): # noqa:N801 is_favorite: bool is_archived: bool can_assign_tasks: bool - view_style: ViewStyle + # Not `ViewStyle`: the API can add view styles, which a Literal would fail to load. + view_style: str created_at: ApiDate updated_at: ApiDate