Skip to content

Commit 27f3aee

Browse files
Merge pull request #188 from Doist/docs
2 parents 6f6f1a3 + 36d1bb7 commit 27f3aee

File tree

13 files changed

+545
-54
lines changed

13 files changed

+545
-54
lines changed

README.md

Lines changed: 22 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,48 @@
11
# Todoist API Python Client
22

3-
This is the official Python API client for the Todoist REST API.
3+
This is the official Python SDK for the Todoist API.
44

5-
### Installation
5+
## Installation
66

7-
The repository can be included as a dependency in `pyproject.toml`.
8-
It is best to integrate to a release tag to ensure a stable dependency:
7+
```bash
8+
pip install todoist-api-python
9+
```
10+
11+
Or add the project as a dependency in `pyproject.toml`:
912

1013
```toml
1114
dependencies = [
12-
...
1315
"todoist-api-python>=3.0.0,<4",
14-
...
1516
]
1617
```
1718

1819
### Supported Python Versions
1920

2021
While we only actively test under Python 3.13, we strive to support all versions from Python 3.9 and above.
2122

22-
### Usage
23+
## Usage
2324

24-
An example of initializing the API client and fetching a user's tasks:
25+
Here's an example of initializing the API client, fetching a task, and paginating through its comments:
2526

2627
```python
27-
from todoist_api_python.api_async import TodoistAPIAsync
2828
from todoist_api_python.api import TodoistAPI
2929

30-
# Fetch tasks synchronously
31-
def get_tasks_sync():
32-
api = TodoistAPI("my token")
33-
try:
34-
tasks = api.get_tasks()
35-
print(tasks)
36-
except Exception as error:
37-
print(error)
38-
39-
# Fetch tasks asynchronously
40-
async def get_tasks_async():
41-
api = TodoistAPIAsync("YOURTOKEN")
42-
try:
43-
tasks = await api.get_tasks()
44-
print(tasks)
45-
except Exception as error:
46-
print(error)
47-
```
48-
49-
Example of paginating through a completed project tasks:
50-
51-
```python
52-
def get_all_completed_items(original_params: dict):
53-
params = original_params.copy()
54-
results = []
55-
56-
while True:
57-
response = api.get_completed_items(**(params | {"limit": 100}))
58-
results.append(response.items)
59-
60-
if not response.has_more:
61-
break
62-
63-
params["cursor"] = response.next_cursor
30+
api = TodoistAPI("YOUR_API_TOKEN")
6431

65-
# flatten the results
66-
return [item for sublist in results for item in sublist]
32+
task = api.get_task("6X4Vw2Hfmg73Q2XR")
33+
print(f"Task: {task.content}")
6734

68-
items = get_all_completed_items({"project_id": 123})
35+
comments_iter = api.get_comments(task_id=task.id)
36+
for comments in comments_iter:
37+
for comment in comments:
38+
print(f"Comment: {comment.content}")
6939
```
7040

71-
### Documentation
41+
## Documentation
7242

73-
For more detailed reference documentation, have a look at the [API documentation with Python examples](https://developer.todoist.com/rest/v2/?python).
43+
For more detailed reference documentation, have a look at the [SDK documentation](https://doist.github.io/todoist-api-python/) and the [API documentation](https://developer.todoist.com).
7444

75-
### Development
45+
## Development
7646

7747
To install Python dependencies:
7848

@@ -104,10 +74,10 @@ A new update is automatically released by GitHub Actions, by creating a release
10474

10575
Users of the API client can then update to the new version in their `pyproject.toml` file.
10676

107-
### Feedback
77+
## Feedback
10878

109-
Any feedback, such as bugs, questions, comments, etc. can be reported as *Issues* in this repository, and will be handled by Doist.
79+
Any feedback, bugs, questions, comments, etc., can be reported as *Issues* in this repository.
11080

11181
### Contributions
11282

113-
We would love contributions in the form of *Pull requests* in this repository.
83+
We would love contributions! *Pull requests* are welcome.

docs/api.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# API Client
2+
3+
::: todoist_api_python.api.TodoistAPI
4+
::: todoist_api_python.api.ResultsPaginator

docs/api_async.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# API Client (async)
2+
3+
::: todoist_api_python.api_async.TodoistAPIAsync

docs/assets/favicon.ico

6.37 KB
Binary file not shown.

docs/assets/logo.svg

Lines changed: 1 addition & 0 deletions
Loading

docs/authentication.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Authentication
2+
3+
This module provides functions to help authenticate with Todoist using the OAuth protocol.
4+
5+
## Quick start
6+
7+
```python
8+
import uuid
9+
from todoist_api_python.authentication import get_access_token, get_authentication_url
10+
11+
# 1. Generate a random state
12+
state = uuid.uuid4()
13+
14+
# 2. Get authorization url
15+
url = get_authentication_url(
16+
client_id="YOUR_CLIENT_ID",
17+
scopes=["data:read", "task:add"],
18+
state=uuid.uuid4()
19+
)
20+
21+
# 3.Redirect user to url
22+
# 4. Handle OAuth callback and get code
23+
code = "CODE_YOU_OBTAINED"
24+
25+
# 5. Exchange code for access token
26+
auth_result = get_access_token(
27+
client_id="YOUR_CLIENT_ID",
28+
client_secret="YOUR_CLIENT_SECRET",
29+
code=code,
30+
)
31+
32+
# 6. Ensure state is consistent, and done!
33+
assert(auth_result.state == state)
34+
access_token = auth_result.access_token
35+
```
36+
37+
For detailed implementation steps and security considerations, refer to the [Todoist OAuth documentation](https://todoist.com/api/v1/docs#tag/Authorization/OAuth).
38+
39+
::: todoist_api_python.authentication

docs/changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--8<-- "CHANGELOG.md"

docs/index.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Overview
2+
3+
This is the official Python SDK for the Todoist API.
4+
5+
## Installation
6+
7+
```bash
8+
pip install todoist-api-python
9+
```
10+
11+
Or add the project as a dependency in `pyproject.toml`:
12+
13+
```toml
14+
dependencies = [
15+
"todoist-api-python>=3.0.0,<4",
16+
]
17+
```
18+
19+
## Usage
20+
21+
Here's an example of initializing the API client, fetching a task, and paginating through its comments:
22+
23+
```python
24+
from todoist_api_python.api import TodoistAPI
25+
26+
api = TodoistAPI("YOUR_API_TOKEN")
27+
28+
task = api.get_task("6X4Vw2Hfmg73Q2XR")
29+
print(f"Task: {task.content}")
30+
31+
comments_iter = api.get_comments(task_id=task.id)
32+
for comments in comments_iter:
33+
for comment in comments:
34+
print(f"Comment: {comment.content}")
35+
```
36+
37+
## Quick start
38+
39+
- [Authentication](authentication.md)
40+
- [API client](api.md)
41+
- [Models](models.md)
42+
43+
## API reference
44+
45+
For detailed reference documentation, have a look at the [API documentation](https://developer.todoist.com/).

docs/models.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Models
2+
3+
::: todoist_api_python.models
4+
options:
5+
show_if_no_docstring: true
6+
show_labels: false
7+
members_order: alphabetical

mkdocs.yml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
site_name: "Todoist Python SDK"
2+
3+
repo_url: https://github.com/Doist/todoist-api-python/
4+
5+
theme:
6+
name: material
7+
logo: assets/logo.svg
8+
favicon: assets/favicon.ico
9+
palette:
10+
- media: "(prefers-color-scheme)"
11+
primary: red
12+
toggle:
13+
icon: material/brightness-4
14+
name: Switch to dark mode
15+
- media: "(prefers-color-scheme: dark)"
16+
scheme: slate
17+
primary: black
18+
toggle:
19+
icon: material/brightness-7
20+
name: Switch to light mode
21+
- media: "(prefers-color-scheme: light)"
22+
scheme: default
23+
primary: red
24+
toggle:
25+
icon: material/brightness-auto
26+
name: Follow system preference
27+
features:
28+
- navigation.footer
29+
30+
extra:
31+
social:
32+
- icon: fontawesome/brands/x-twitter
33+
link: https://x.com/doistdevs
34+
- icon: fontawesome/brands/github
35+
link: https://github.com/doist
36+
37+
markdown_extensions:
38+
- pymdownx.highlight:
39+
anchor_linenums: true
40+
line_spans: __span
41+
pygments_lang_class: true
42+
- pymdownx.inlinehilite
43+
- pymdownx.snippets
44+
- pymdownx.superfences
45+
46+
plugins:
47+
- search
48+
- mkdocstrings:
49+
handlers:
50+
python:
51+
options:
52+
docstring_style: sphinx
53+
backlinks: true
54+
filters: ["!^_"]
55+
show_symbol_type_toc: True
56+
signature_crossrefs: true
57+
unwrap_annotated: true

pyproject.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ dev = [
3434
"ruff>=0.11.0,<0.12",
3535
]
3636

37+
docs = [
38+
"mkdocs>=1.6.1,<2.0.0",
39+
"mkdocstrings[python]>=0.29.1,<1.0.0",
40+
"mkdocs-material>=9.6.11,<10.0.0",
41+
]
42+
3743
[tool.hatch.build.targets.sdist]
3844
include = ["LICENSE"]
3945

todoist_api_python/authentication.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from __future__ import annotations
22

3-
from typing import Any
3+
from typing import Any, Literal
44
from urllib.parse import urlencode
55

66
import requests
@@ -17,8 +17,27 @@
1717
from todoist_api_python._core.utils import run_async
1818
from todoist_api_python.models import AuthResult
1919

20+
# task:add - Only create new tasks
21+
# data:read - Read-only access
22+
# data:read_write - Read and write access
23+
# data:delete - Full access including delete
24+
# project:delete - Can delete projects
2025

21-
def get_authentication_url(client_id: str, scopes: list[str], state: str) -> str:
26+
"""
27+
Possible permission scopes:
28+
29+
- data:read: Read-only access
30+
- data:read_write: Read and write access
31+
- data:delete: Full access including delete
32+
- task:add: Can create new tasks
33+
- project:delete: Can delete projects
34+
"""
35+
Scope = Literal[
36+
"task:add", "data:read", "data:read_write", "data:delete", "project:delete"
37+
]
38+
39+
40+
def get_authentication_url(client_id: str, scopes: list[Scope], state: str) -> str:
2241
"""Get authorization URL to initiate OAuth flow."""
2342
if len(scopes) == 0:
2443
raise ValueError("At least one authorization scope should be requested.")

0 commit comments

Comments
 (0)