Skip to content

Tag#

pyticktick.models.v2.parameters.tag #

Parameters for creating and update tags via the V2 API.

Unofficial API

These models are part of the unofficial TickTick API. They were created by reverse engineering the API. They may be incomplete or inaccurate.

Classes:

Name Description
CreateTagV2

Model for creating a tag via the V2 API.

DeleteTagV2

Model for deleting a tag via the V2 API.

PostBatchTagV2

Model for batch tag operations via the V2 API.

RenameTagV2

Model for renaming a tag via the V2 API.

UpdateTagV2

Model for updating a tag via the V2 API.

CreateTagV2 pydantic-model #

Bases: BaseModelV2

Model for creating a tag via the V2 API.

This model is used to create a tag via the V2 API. This is not currently documented or supported in the official API docs. This is used in the PostBatchTagV2 model.

Show JSON schema:
{
  "additionalProperties": false,
  "description": "Model for creating a tag via the V2 API.\n\nThis model is used to create a tag via the V2 API. This is not currently documented\nor supported in the official API docs. This is used in the `PostBatchTagV2` model.",
  "properties": {
    "label": {
      "description": "Name of the tag to create",
      "pattern": "^[^\\\\\\/\\\"#:*?<>|\\s]+$",
      "title": "Label",
      "type": "string"
    },
    "color": {
      "anyOf": [
        {
          "format": "color",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Color of the tag, eg. '#F18181'",
      "title": "Color"
    },
    "name": {
      "anyOf": [
        {
          "pattern": "^[^\\\\\\/\\\"#:*?<>|\\sA-Z]+$",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Name of the tag to create",
      "title": "Name"
    },
    "parent": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Name of the parent tag",
      "title": "Parent"
    },
    "sort_type": {
      "default": "project",
      "description": "Sort type when displaying by selected tag",
      "enum": [
        "project",
        "title",
        "tag"
      ],
      "title": "Sort Type",
      "type": "string"
    },
    "sort_order": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Sort Order"
    }
  },
  "required": [
    "label"
  ],
  "title": "CreateTagV2",
  "type": "object"
}

Fields:

Validators:

color pydantic-field #

color: Color | None = None

Color of the tag, eg. '#F18181'

label pydantic-field #

label: TagLabel

Name of the tag to create

name pydantic-field #

name: TagName | None = None

Name of the tag to create

parent pydantic-field #

parent: str | None = None

Name of the parent tag

sort_type pydantic-field #

sort_type: Literal['project', 'title', 'tag'] = 'project'

Sort type when displaying by selected tag

empty_str_to_none pydantic-validator #

empty_str_to_none(v: Any) -> Any

Convert empty strings to None.

TickTick API responses sometimes conflates None and empty strings for optional fields. This validator ensures that empty strings are converted to None, which then allows for more consistent handling of the data within the library.

Parameters:

Name Type Description Default
v Any

The value to validate.

required

Returns:

Name Type Description
Any Any

The input value if it is not an empty string, otherwise None.

Source code in src/pyticktick/models/v2/models.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
@field_validator("*", mode="before")
@classmethod
def empty_str_to_none(cls, v: Any) -> Any:
    """Convert empty strings to None.

    TickTick API responses sometimes conflates `None` and empty strings for
    optional fields. This validator ensures that empty strings are converted to
    `None`, which then allows for more consistent handling of the data within the
    library.

    Args:
        v (Any): The value to validate.

    Returns:
        Any: The input value if it is not an empty string, otherwise `None`.
    """
    if isinstance(v, str) and len(v) == 0:
        return None
    return v

override_forbid_extra_message_injector pydantic-validator #

override_forbid_extra_message_injector(
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2

Provide a better error message for extra fields.

The TickTick V2 API is unofficial and may change without notice. As such, the models may not always be up to date with the API. This validator catches the extra_forbidden errors and provides a more informative error message, including a link to the documentation on how to override the extra_forbidden behavior if needed.

Parameters:

Name Type Description Default
data Any

The input data to validate.

required
handler ModelWrapValidatorHandler[BaseModelV2]

The handler to call the next validator in the chain.

required

Raises:

Type Description
ValidationError

If the pydantic model fails validation for any reason.

Returns:

Name Type Description
BaseModelV2 BaseModelV2

The validated model instance.

Source code in src/pyticktick/models/v2/models.py
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
@model_validator(mode="wrap")
@classmethod
def override_forbid_extra_message_injector(
    cls,
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2:
    """Provide a better error message for extra fields.

    The TickTick V2 API is unofficial and may change without notice. As such, the
    models may not always be up to date with the API. This validator catches the
    `extra_forbidden` errors and provides a more informative error message,
    including a link to the documentation on how to override the `extra_forbidden`
    behavior if needed.

    Args:
        data (Any): The input data to validate.
        handler (ModelWrapValidatorHandler[BaseModelV2]): The handler to call the
            next validator in the chain.

    Raises:
        ValidationError: If the pydantic model fails validation for any reason.

    Returns:
        BaseModelV2: The validated model instance.
    """  # noqa: DOC501, DOC502 # ruff thinks `from_exception_data` should be raised instead of `ValidationError`
    try:
        return handler(data)
    except ValidationError as e:
        errors = []
        for error_dict in e.errors():
            if error_dict.get("type") in (
                "extra_forbidden",
                "custom_pyticktick_extra_forbidden",
            ):
                _type: str | PydanticCustomError = PydanticCustomError(
                    "custom_pyticktick_extra_forbidden",
                    f"Extra inputs are not permitted by default for `{cls.__name__}`. Please set `override_forbid_extra` to `True` if you believe the TickTick API has diverged from the model. See https://pyticktick.pretzer.io/guides/settings/overriding_models_that_forbid_extra_fields/ for more information.",  # pyright: ignore[reportArgumentType] # ty: ignore[invalid-argument-type]
                )
            else:
                _type = error_dict["type"]

            init_error_details: InitErrorDetails = {
                "type": _type,
                "input": error_dict["input"],
            }
            if "loc" in error_dict:
                init_error_details["loc"] = error_dict["loc"]
            if "ctx" in error_dict:
                init_error_details["ctx"] = error_dict["ctx"]

            errors.append(init_error_details)

        raise ValidationError.from_exception_data(e.title, errors) from e

DeleteTagV2 pydantic-model #

Bases: BaseModelV2

Model for deleting a tag via the V2 API.

This model is used to delete a tag against the V2 API endpoint DELETE /tag. This is not currently documented or supported in the official API docs.

Show JSON schema:
{
  "additionalProperties": false,
  "description": "Model for deleting a tag via the V2 API.\n\nThis model is used to delete a tag against the V2 API endpoint `DELETE /tag`. This\nis not currently documented or supported in the official API docs.",
  "properties": {
    "name": {
      "description": "Identifier of the tag to delete",
      "title": "Name",
      "type": "string"
    }
  },
  "required": [
    "name"
  ],
  "title": "DeleteTagV2",
  "type": "object"
}

Fields:

Validators:

name pydantic-field #

name: str

Identifier of the tag to delete

empty_str_to_none pydantic-validator #

empty_str_to_none(v: Any) -> Any

Convert empty strings to None.

TickTick API responses sometimes conflates None and empty strings for optional fields. This validator ensures that empty strings are converted to None, which then allows for more consistent handling of the data within the library.

Parameters:

Name Type Description Default
v Any

The value to validate.

required

Returns:

Name Type Description
Any Any

The input value if it is not an empty string, otherwise None.

Source code in src/pyticktick/models/v2/models.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
@field_validator("*", mode="before")
@classmethod
def empty_str_to_none(cls, v: Any) -> Any:
    """Convert empty strings to None.

    TickTick API responses sometimes conflates `None` and empty strings for
    optional fields. This validator ensures that empty strings are converted to
    `None`, which then allows for more consistent handling of the data within the
    library.

    Args:
        v (Any): The value to validate.

    Returns:
        Any: The input value if it is not an empty string, otherwise `None`.
    """
    if isinstance(v, str) and len(v) == 0:
        return None
    return v

override_forbid_extra_message_injector pydantic-validator #

override_forbid_extra_message_injector(
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2

Provide a better error message for extra fields.

The TickTick V2 API is unofficial and may change without notice. As such, the models may not always be up to date with the API. This validator catches the extra_forbidden errors and provides a more informative error message, including a link to the documentation on how to override the extra_forbidden behavior if needed.

Parameters:

Name Type Description Default
data Any

The input data to validate.

required
handler ModelWrapValidatorHandler[BaseModelV2]

The handler to call the next validator in the chain.

required

Raises:

Type Description
ValidationError

If the pydantic model fails validation for any reason.

Returns:

Name Type Description
BaseModelV2 BaseModelV2

The validated model instance.

Source code in src/pyticktick/models/v2/models.py
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
@model_validator(mode="wrap")
@classmethod
def override_forbid_extra_message_injector(
    cls,
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2:
    """Provide a better error message for extra fields.

    The TickTick V2 API is unofficial and may change without notice. As such, the
    models may not always be up to date with the API. This validator catches the
    `extra_forbidden` errors and provides a more informative error message,
    including a link to the documentation on how to override the `extra_forbidden`
    behavior if needed.

    Args:
        data (Any): The input data to validate.
        handler (ModelWrapValidatorHandler[BaseModelV2]): The handler to call the
            next validator in the chain.

    Raises:
        ValidationError: If the pydantic model fails validation for any reason.

    Returns:
        BaseModelV2: The validated model instance.
    """  # noqa: DOC501, DOC502 # ruff thinks `from_exception_data` should be raised instead of `ValidationError`
    try:
        return handler(data)
    except ValidationError as e:
        errors = []
        for error_dict in e.errors():
            if error_dict.get("type") in (
                "extra_forbidden",
                "custom_pyticktick_extra_forbidden",
            ):
                _type: str | PydanticCustomError = PydanticCustomError(
                    "custom_pyticktick_extra_forbidden",
                    f"Extra inputs are not permitted by default for `{cls.__name__}`. Please set `override_forbid_extra` to `True` if you believe the TickTick API has diverged from the model. See https://pyticktick.pretzer.io/guides/settings/overriding_models_that_forbid_extra_fields/ for more information.",  # pyright: ignore[reportArgumentType] # ty: ignore[invalid-argument-type]
                )
            else:
                _type = error_dict["type"]

            init_error_details: InitErrorDetails = {
                "type": _type,
                "input": error_dict["input"],
            }
            if "loc" in error_dict:
                init_error_details["loc"] = error_dict["loc"]
            if "ctx" in error_dict:
                init_error_details["ctx"] = error_dict["ctx"]

            errors.append(init_error_details)

        raise ValidationError.from_exception_data(e.title, errors) from e

PostBatchTagV2 pydantic-model #

Bases: BaseModelV2

Model for batch tag operations via the V2 API.

This model is used to batch create, and update tags in bulk against the V2 API endpoint POST /batch/tag.

Note

While batch operations usually support adding, updating, and deleting, this endpoint only supports adding and updating tags. Deleting tags supported separately.

Show JSON schema:
{
  "$defs": {
    "CreateTagV2": {
      "additionalProperties": false,
      "description": "Model for creating a tag via the V2 API.\n\nThis model is used to create a tag via the V2 API. This is not currently documented\nor supported in the official API docs. This is used in the `PostBatchTagV2` model.",
      "properties": {
        "label": {
          "description": "Name of the tag to create",
          "pattern": "^[^\\\\\\/\\\"#:*?<>|\\s]+$",
          "title": "Label",
          "type": "string"
        },
        "color": {
          "anyOf": [
            {
              "format": "color",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Color of the tag, eg. '#F18181'",
          "title": "Color"
        },
        "name": {
          "anyOf": [
            {
              "pattern": "^[^\\\\\\/\\\"#:*?<>|\\sA-Z]+$",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Name of the tag to create",
          "title": "Name"
        },
        "parent": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Name of the parent tag",
          "title": "Parent"
        },
        "sort_type": {
          "default": "project",
          "description": "Sort type when displaying by selected tag",
          "enum": [
            "project",
            "title",
            "tag"
          ],
          "title": "Sort Type",
          "type": "string"
        },
        "sort_order": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Sort Order"
        }
      },
      "required": [
        "label"
      ],
      "title": "CreateTagV2",
      "type": "object"
    },
    "UpdateTagV2": {
      "additionalProperties": false,
      "description": "Model for updating a tag via the V2 API.\n\nThis model is used to update a tag via the V2 API. This is not currently documented\nor supported in the official API docs. This is used in the `PostBatchTagV2` model.",
      "properties": {
        "label": {
          "description": "Name of the tag to update",
          "pattern": "^[^\\\\\\/\\\"#:*?<>|\\s]+$",
          "title": "Label",
          "type": "string"
        },
        "color": {
          "anyOf": [
            {
              "format": "color",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Color of the tag, eg. '#F18181'",
          "title": "Color"
        },
        "name": {
          "anyOf": [
            {
              "pattern": "^[^\\\\\\/\\\"#:*?<>|\\sA-Z]+$",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Stand-in for the identifier of the tag, by default will be the tag label, but lowercase, it is recommended to not specify this field",
          "title": "Name"
        },
        "parent": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Name of the parent tag",
          "title": "Parent"
        },
        "raw_name": {
          "anyOf": [
            {
              "pattern": "^[^\\\\\\/\\\"#:*?<>|\\sA-Z]+$",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Original name of the tag, used to identify it",
          "title": "Raw Name"
        },
        "sort_type": {
          "default": "project",
          "description": "Sort type when displaying by selected tag",
          "enum": [
            "project",
            "title",
            "tag"
          ],
          "title": "Sort Type",
          "type": "string"
        },
        "sort_order": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Sort Order"
        }
      },
      "required": [
        "label"
      ],
      "title": "UpdateTagV2",
      "type": "object"
    }
  },
  "additionalProperties": false,
  "description": "Model for batch tag operations via the V2 API.\n\nThis model is used to batch create, and update tags in bulk against the V2 API\nendpoint `POST /batch/tag`.\n\n!!! note\n    While batch operations usually support adding, updating, and deleting, this\n    endpoint only supports adding and updating tags. Deleting tags supported\n    separately.",
  "properties": {
    "add": {
      "default": [],
      "description": "List of tags to add",
      "items": {
        "$ref": "#/$defs/CreateTagV2"
      },
      "title": "Add",
      "type": "array"
    },
    "update": {
      "default": [],
      "description": "List of tags to update",
      "items": {
        "$ref": "#/$defs/UpdateTagV2"
      },
      "title": "Update",
      "type": "array"
    }
  },
  "title": "PostBatchTagV2",
  "type": "object"
}

Fields:

Validators:

add pydantic-field #

add: list[CreateTagV2] = []

List of tags to add

update pydantic-field #

update: list[UpdateTagV2] = []

List of tags to update

empty_str_to_none pydantic-validator #

empty_str_to_none(v: Any) -> Any

Convert empty strings to None.

TickTick API responses sometimes conflates None and empty strings for optional fields. This validator ensures that empty strings are converted to None, which then allows for more consistent handling of the data within the library.

Parameters:

Name Type Description Default
v Any

The value to validate.

required

Returns:

Name Type Description
Any Any

The input value if it is not an empty string, otherwise None.

Source code in src/pyticktick/models/v2/models.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
@field_validator("*", mode="before")
@classmethod
def empty_str_to_none(cls, v: Any) -> Any:
    """Convert empty strings to None.

    TickTick API responses sometimes conflates `None` and empty strings for
    optional fields. This validator ensures that empty strings are converted to
    `None`, which then allows for more consistent handling of the data within the
    library.

    Args:
        v (Any): The value to validate.

    Returns:
        Any: The input value if it is not an empty string, otherwise `None`.
    """
    if isinstance(v, str) and len(v) == 0:
        return None
    return v

override_forbid_extra_message_injector pydantic-validator #

override_forbid_extra_message_injector(
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2

Provide a better error message for extra fields.

The TickTick V2 API is unofficial and may change without notice. As such, the models may not always be up to date with the API. This validator catches the extra_forbidden errors and provides a more informative error message, including a link to the documentation on how to override the extra_forbidden behavior if needed.

Parameters:

Name Type Description Default
data Any

The input data to validate.

required
handler ModelWrapValidatorHandler[BaseModelV2]

The handler to call the next validator in the chain.

required

Raises:

Type Description
ValidationError

If the pydantic model fails validation for any reason.

Returns:

Name Type Description
BaseModelV2 BaseModelV2

The validated model instance.

Source code in src/pyticktick/models/v2/models.py
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
@model_validator(mode="wrap")
@classmethod
def override_forbid_extra_message_injector(
    cls,
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2:
    """Provide a better error message for extra fields.

    The TickTick V2 API is unofficial and may change without notice. As such, the
    models may not always be up to date with the API. This validator catches the
    `extra_forbidden` errors and provides a more informative error message,
    including a link to the documentation on how to override the `extra_forbidden`
    behavior if needed.

    Args:
        data (Any): The input data to validate.
        handler (ModelWrapValidatorHandler[BaseModelV2]): The handler to call the
            next validator in the chain.

    Raises:
        ValidationError: If the pydantic model fails validation for any reason.

    Returns:
        BaseModelV2: The validated model instance.
    """  # noqa: DOC501, DOC502 # ruff thinks `from_exception_data` should be raised instead of `ValidationError`
    try:
        return handler(data)
    except ValidationError as e:
        errors = []
        for error_dict in e.errors():
            if error_dict.get("type") in (
                "extra_forbidden",
                "custom_pyticktick_extra_forbidden",
            ):
                _type: str | PydanticCustomError = PydanticCustomError(
                    "custom_pyticktick_extra_forbidden",
                    f"Extra inputs are not permitted by default for `{cls.__name__}`. Please set `override_forbid_extra` to `True` if you believe the TickTick API has diverged from the model. See https://pyticktick.pretzer.io/guides/settings/overriding_models_that_forbid_extra_fields/ for more information.",  # pyright: ignore[reportArgumentType] # ty: ignore[invalid-argument-type]
                )
            else:
                _type = error_dict["type"]

            init_error_details: InitErrorDetails = {
                "type": _type,
                "input": error_dict["input"],
            }
            if "loc" in error_dict:
                init_error_details["loc"] = error_dict["loc"]
            if "ctx" in error_dict:
                init_error_details["ctx"] = error_dict["ctx"]

            errors.append(init_error_details)

        raise ValidationError.from_exception_data(e.title, errors) from e

RenameTagV2 pydantic-model #

Bases: BaseModelV2

Model for renaming a tag via the V2 API.

This model is used to rename a tag via the V2 API endpoint PUT /tag/rename. This is not currently documented or supported in the official API docs.

Show JSON schema:
{
  "additionalProperties": false,
  "description": "Model for renaming a tag via the V2 API.\n\nThis model is used to rename a tag via the V2 API endpoint `PUT /tag/rename`. This\nis not currently documented or supported in the official API docs.",
  "properties": {
    "name": {
      "description": "Identifier of the tag to rename",
      "pattern": "^[^\\\\\\/\\\"#:*?<>|\\sA-Z]+$",
      "title": "Name",
      "type": "string"
    },
    "new_name": {
      "description": "New name for the tag",
      "pattern": "^[^\\\\\\/\\\"#:*?<>|\\s]+$",
      "title": "New Name",
      "type": "string"
    }
  },
  "required": [
    "name",
    "new_name"
  ],
  "title": "RenameTagV2",
  "type": "object"
}

Fields:

Validators:

name pydantic-field #

name: TagName

Identifier of the tag to rename

new_name pydantic-field #

new_name: TagLabel

New name for the tag

empty_str_to_none pydantic-validator #

empty_str_to_none(v: Any) -> Any

Convert empty strings to None.

TickTick API responses sometimes conflates None and empty strings for optional fields. This validator ensures that empty strings are converted to None, which then allows for more consistent handling of the data within the library.

Parameters:

Name Type Description Default
v Any

The value to validate.

required

Returns:

Name Type Description
Any Any

The input value if it is not an empty string, otherwise None.

Source code in src/pyticktick/models/v2/models.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
@field_validator("*", mode="before")
@classmethod
def empty_str_to_none(cls, v: Any) -> Any:
    """Convert empty strings to None.

    TickTick API responses sometimes conflates `None` and empty strings for
    optional fields. This validator ensures that empty strings are converted to
    `None`, which then allows for more consistent handling of the data within the
    library.

    Args:
        v (Any): The value to validate.

    Returns:
        Any: The input value if it is not an empty string, otherwise `None`.
    """
    if isinstance(v, str) and len(v) == 0:
        return None
    return v

override_forbid_extra_message_injector pydantic-validator #

override_forbid_extra_message_injector(
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2

Provide a better error message for extra fields.

The TickTick V2 API is unofficial and may change without notice. As such, the models may not always be up to date with the API. This validator catches the extra_forbidden errors and provides a more informative error message, including a link to the documentation on how to override the extra_forbidden behavior if needed.

Parameters:

Name Type Description Default
data Any

The input data to validate.

required
handler ModelWrapValidatorHandler[BaseModelV2]

The handler to call the next validator in the chain.

required

Raises:

Type Description
ValidationError

If the pydantic model fails validation for any reason.

Returns:

Name Type Description
BaseModelV2 BaseModelV2

The validated model instance.

Source code in src/pyticktick/models/v2/models.py
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
@model_validator(mode="wrap")
@classmethod
def override_forbid_extra_message_injector(
    cls,
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2:
    """Provide a better error message for extra fields.

    The TickTick V2 API is unofficial and may change without notice. As such, the
    models may not always be up to date with the API. This validator catches the
    `extra_forbidden` errors and provides a more informative error message,
    including a link to the documentation on how to override the `extra_forbidden`
    behavior if needed.

    Args:
        data (Any): The input data to validate.
        handler (ModelWrapValidatorHandler[BaseModelV2]): The handler to call the
            next validator in the chain.

    Raises:
        ValidationError: If the pydantic model fails validation for any reason.

    Returns:
        BaseModelV2: The validated model instance.
    """  # noqa: DOC501, DOC502 # ruff thinks `from_exception_data` should be raised instead of `ValidationError`
    try:
        return handler(data)
    except ValidationError as e:
        errors = []
        for error_dict in e.errors():
            if error_dict.get("type") in (
                "extra_forbidden",
                "custom_pyticktick_extra_forbidden",
            ):
                _type: str | PydanticCustomError = PydanticCustomError(
                    "custom_pyticktick_extra_forbidden",
                    f"Extra inputs are not permitted by default for `{cls.__name__}`. Please set `override_forbid_extra` to `True` if you believe the TickTick API has diverged from the model. See https://pyticktick.pretzer.io/guides/settings/overriding_models_that_forbid_extra_fields/ for more information.",  # pyright: ignore[reportArgumentType] # ty: ignore[invalid-argument-type]
                )
            else:
                _type = error_dict["type"]

            init_error_details: InitErrorDetails = {
                "type": _type,
                "input": error_dict["input"],
            }
            if "loc" in error_dict:
                init_error_details["loc"] = error_dict["loc"]
            if "ctx" in error_dict:
                init_error_details["ctx"] = error_dict["ctx"]

            errors.append(init_error_details)

        raise ValidationError.from_exception_data(e.title, errors) from e

UpdateTagV2 pydantic-model #

Bases: BaseModelV2

Model for updating a tag via the V2 API.

This model is used to update a tag via the V2 API. This is not currently documented or supported in the official API docs. This is used in the PostBatchTagV2 model.

Show JSON schema:
{
  "additionalProperties": false,
  "description": "Model for updating a tag via the V2 API.\n\nThis model is used to update a tag via the V2 API. This is not currently documented\nor supported in the official API docs. This is used in the `PostBatchTagV2` model.",
  "properties": {
    "label": {
      "description": "Name of the tag to update",
      "pattern": "^[^\\\\\\/\\\"#:*?<>|\\s]+$",
      "title": "Label",
      "type": "string"
    },
    "color": {
      "anyOf": [
        {
          "format": "color",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Color of the tag, eg. '#F18181'",
      "title": "Color"
    },
    "name": {
      "anyOf": [
        {
          "pattern": "^[^\\\\\\/\\\"#:*?<>|\\sA-Z]+$",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Stand-in for the identifier of the tag, by default will be the tag label, but lowercase, it is recommended to not specify this field",
      "title": "Name"
    },
    "parent": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Name of the parent tag",
      "title": "Parent"
    },
    "raw_name": {
      "anyOf": [
        {
          "pattern": "^[^\\\\\\/\\\"#:*?<>|\\sA-Z]+$",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Original name of the tag, used to identify it",
      "title": "Raw Name"
    },
    "sort_type": {
      "default": "project",
      "description": "Sort type when displaying by selected tag",
      "enum": [
        "project",
        "title",
        "tag"
      ],
      "title": "Sort Type",
      "type": "string"
    },
    "sort_order": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Sort Order"
    }
  },
  "required": [
    "label"
  ],
  "title": "UpdateTagV2",
  "type": "object"
}

Fields:

Validators:

color pydantic-field #

color: Color | None = None

Color of the tag, eg. '#F18181'

label pydantic-field #

label: TagLabel

Name of the tag to update

name pydantic-field #

name: TagName | None = None

Stand-in for the identifier of the tag, by default will be the tag label, but lowercase, it is recommended to not specify this field

parent pydantic-field #

parent: str | None = None

Name of the parent tag

raw_name pydantic-field #

raw_name: TagName | None = None

Original name of the tag, used to identify it

sort_type pydantic-field #

sort_type: Literal['project', 'title', 'tag'] = 'project'

Sort type when displaying by selected tag

empty_str_to_none pydantic-validator #

empty_str_to_none(v: Any) -> Any

Convert empty strings to None.

TickTick API responses sometimes conflates None and empty strings for optional fields. This validator ensures that empty strings are converted to None, which then allows for more consistent handling of the data within the library.

Parameters:

Name Type Description Default
v Any

The value to validate.

required

Returns:

Name Type Description
Any Any

The input value if it is not an empty string, otherwise None.

Source code in src/pyticktick/models/v2/models.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
@field_validator("*", mode="before")
@classmethod
def empty_str_to_none(cls, v: Any) -> Any:
    """Convert empty strings to None.

    TickTick API responses sometimes conflates `None` and empty strings for
    optional fields. This validator ensures that empty strings are converted to
    `None`, which then allows for more consistent handling of the data within the
    library.

    Args:
        v (Any): The value to validate.

    Returns:
        Any: The input value if it is not an empty string, otherwise `None`.
    """
    if isinstance(v, str) and len(v) == 0:
        return None
    return v

override_forbid_extra_message_injector pydantic-validator #

override_forbid_extra_message_injector(
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2

Provide a better error message for extra fields.

The TickTick V2 API is unofficial and may change without notice. As such, the models may not always be up to date with the API. This validator catches the extra_forbidden errors and provides a more informative error message, including a link to the documentation on how to override the extra_forbidden behavior if needed.

Parameters:

Name Type Description Default
data Any

The input data to validate.

required
handler ModelWrapValidatorHandler[BaseModelV2]

The handler to call the next validator in the chain.

required

Raises:

Type Description
ValidationError

If the pydantic model fails validation for any reason.

Returns:

Name Type Description
BaseModelV2 BaseModelV2

The validated model instance.

Source code in src/pyticktick/models/v2/models.py
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
@model_validator(mode="wrap")
@classmethod
def override_forbid_extra_message_injector(
    cls,
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2:
    """Provide a better error message for extra fields.

    The TickTick V2 API is unofficial and may change without notice. As such, the
    models may not always be up to date with the API. This validator catches the
    `extra_forbidden` errors and provides a more informative error message,
    including a link to the documentation on how to override the `extra_forbidden`
    behavior if needed.

    Args:
        data (Any): The input data to validate.
        handler (ModelWrapValidatorHandler[BaseModelV2]): The handler to call the
            next validator in the chain.

    Raises:
        ValidationError: If the pydantic model fails validation for any reason.

    Returns:
        BaseModelV2: The validated model instance.
    """  # noqa: DOC501, DOC502 # ruff thinks `from_exception_data` should be raised instead of `ValidationError`
    try:
        return handler(data)
    except ValidationError as e:
        errors = []
        for error_dict in e.errors():
            if error_dict.get("type") in (
                "extra_forbidden",
                "custom_pyticktick_extra_forbidden",
            ):
                _type: str | PydanticCustomError = PydanticCustomError(
                    "custom_pyticktick_extra_forbidden",
                    f"Extra inputs are not permitted by default for `{cls.__name__}`. Please set `override_forbid_extra` to `True` if you believe the TickTick API has diverged from the model. See https://pyticktick.pretzer.io/guides/settings/overriding_models_that_forbid_extra_fields/ for more information.",  # pyright: ignore[reportArgumentType] # ty: ignore[invalid-argument-type]
                )
            else:
                _type = error_dict["type"]

            init_error_details: InitErrorDetails = {
                "type": _type,
                "input": error_dict["input"],
            }
            if "loc" in error_dict:
                init_error_details["loc"] = error_dict["loc"]
            if "ctx" in error_dict:
                init_error_details["ctx"] = error_dict["ctx"]

            errors.append(init_error_details)

        raise ValidationError.from_exception_data(e.title, errors) from e