things-api 0.1.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- things_api-0.2.1/.github/workflows/publish.yml +56 -0
- {things_api-0.1.0 → things_api-0.2.1}/CHANGELOG.md +11 -0
- {things_api-0.1.0 → things_api-0.2.1}/PKG-INFO +20 -11
- {things_api-0.1.0 → things_api-0.2.1}/README.md +19 -10
- {things_api-0.1.0 → things_api-0.2.1}/com.things-api.server.plist +11 -12
- {things_api-0.1.0 → things_api-0.2.1}/docs/deployment.md +17 -5
- {things_api-0.1.0 → things_api-0.2.1}/pyproject.toml +1 -1
- {things_api-0.1.0 → things_api-0.2.1}/src/things_api/app.py +13 -1
- {things_api-0.1.0 → things_api-0.2.1}/uv.lock +1 -1
- {things_api-0.1.0 → things_api-0.2.1}/.gitignore +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/LICENSE +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/docs/api-reference.md +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/docs/configuration.md +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/docs/development.md +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/docs/plans/2026-04-03-things-api-design.md +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/docs/plans/2026-04-03-things-api-plan.md +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/docs/plans/2026-04-03-things-api-plan.md.tasks.json +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/env.example +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/src/things_api/__init__.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/src/things_api/auth.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/src/things_api/config.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/src/things_api/models.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/src/things_api/ratelimit.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/src/things_api/routers/__init__.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/src/things_api/routers/areas.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/src/things_api/routers/lists.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/src/things_api/routers/projects.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/src/things_api/routers/search.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/src/things_api/routers/tags.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/src/things_api/routers/todos.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/src/things_api/services/__init__.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/src/things_api/services/reader.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/src/things_api/services/writer.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/tests/__init__.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/tests/conftest.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/tests/test_app.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/tests/test_auth.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/tests/test_config.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/tests/test_models.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/tests/test_ratelimit.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/tests/test_reader.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/tests/test_router_areas.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/tests/test_router_lists.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/tests/test_router_projects.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/tests/test_router_search.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/tests/test_router_tags.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/tests/test_router_todos.py +0 -0
- {things_api-0.1.0 → things_api-0.2.1}/tests/test_writer.py +0 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
|
|
14
|
+
- name: Install uv
|
|
15
|
+
uses: astral-sh/setup-uv@v6
|
|
16
|
+
|
|
17
|
+
- name: Set up Python
|
|
18
|
+
run: uv python install 3.12
|
|
19
|
+
|
|
20
|
+
- name: Install dependencies
|
|
21
|
+
run: uv sync --extra test
|
|
22
|
+
|
|
23
|
+
- name: Run tests
|
|
24
|
+
run: uv run pytest -v
|
|
25
|
+
|
|
26
|
+
publish:
|
|
27
|
+
needs: test
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
environment: pypi
|
|
30
|
+
permissions:
|
|
31
|
+
id-token: write
|
|
32
|
+
contents: read
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
|
|
36
|
+
- name: Install uv
|
|
37
|
+
uses: astral-sh/setup-uv@v6
|
|
38
|
+
|
|
39
|
+
- name: Set up Python
|
|
40
|
+
run: uv python install 3.12
|
|
41
|
+
|
|
42
|
+
- name: Check version consistency
|
|
43
|
+
run: |
|
|
44
|
+
TAG_VERSION="${GITHUB_REF_NAME#v}"
|
|
45
|
+
PYPROJECT_VERSION=$(uv run python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
|
|
46
|
+
if [ "$TAG_VERSION" != "$PYPROJECT_VERSION" ]; then
|
|
47
|
+
echo "::error::Tag version ($TAG_VERSION) does not match pyproject.toml version ($PYPROJECT_VERSION)"
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
echo "Version $TAG_VERSION confirmed"
|
|
51
|
+
|
|
52
|
+
- name: Build
|
|
53
|
+
run: uv build
|
|
54
|
+
|
|
55
|
+
- name: Publish to PyPI
|
|
56
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
This project follows [Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [0.2.1] — 2026-04-03
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Published to [PyPI](https://pypi.org/project/things-api/) — install with `pip install things-api` or run with `uvx things-api`
|
|
12
|
+
- GitHub Actions CI/CD pipeline with tag-driven PyPI publishing via trusted publishers (OIDC)
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- Friendly error message when `THINGS_API_TOKEN` is missing instead of a Pydantic traceback
|
|
17
|
+
|
|
7
18
|
## [0.1.0] — 2026-04-03
|
|
8
19
|
|
|
9
20
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: things-api
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: REST API for Things 3 — expose your tasks over HTTP
|
|
5
5
|
Project-URL: Homepage, https://github.com/jaydenk/things-api
|
|
6
6
|
Project-URL: Documentation, https://github.com/jaydenk/things-api/tree/main/docs
|
|
@@ -36,24 +36,33 @@ Things API reads directly from the Things SQLite database via [things.py](https:
|
|
|
36
36
|
|
|
37
37
|
## Getting started
|
|
38
38
|
|
|
39
|
-
**Requirements:** macOS with [Things 3](https://culturedcode.com/things/) installed
|
|
39
|
+
**Requirements:** macOS with [Things 3](https://culturedcode.com/things/) installed and Python 3.12+.
|
|
40
40
|
|
|
41
|
-
### 1.
|
|
41
|
+
### 1. Install
|
|
42
|
+
|
|
43
|
+
Run directly with [`uvx`](https://docs.astral.sh/uv/) (no install needed):
|
|
42
44
|
|
|
43
45
|
```sh
|
|
44
|
-
|
|
45
|
-
cd things-api
|
|
46
|
-
uv venv
|
|
47
|
-
uv pip install -e .
|
|
46
|
+
uvx things-api
|
|
48
47
|
```
|
|
49
48
|
|
|
50
|
-
|
|
49
|
+
Or install with pip:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
pip install things-api
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Or clone the repo for development:
|
|
51
56
|
|
|
52
57
|
```sh
|
|
53
|
-
|
|
58
|
+
git clone https://github.com/jaydenk/things-api.git
|
|
59
|
+
cd things-api
|
|
60
|
+
uv venv && uv pip install -e .
|
|
54
61
|
```
|
|
55
62
|
|
|
56
|
-
|
|
63
|
+
### 2. Configure
|
|
64
|
+
|
|
65
|
+
Create a `.env` file in the directory you'll run the server from:
|
|
57
66
|
|
|
58
67
|
```dotenv
|
|
59
68
|
THINGS_API_TOKEN=choose-a-secure-random-string
|
|
@@ -72,7 +81,7 @@ See [docs/configuration.md](docs/configuration.md) for all configuration options
|
|
|
72
81
|
### 3. Run
|
|
73
82
|
|
|
74
83
|
```sh
|
|
75
|
-
|
|
84
|
+
things-api
|
|
76
85
|
```
|
|
77
86
|
|
|
78
87
|
The server starts on `http://localhost:5225`.
|
|
@@ -6,24 +6,33 @@ Things API reads directly from the Things SQLite database via [things.py](https:
|
|
|
6
6
|
|
|
7
7
|
## Getting started
|
|
8
8
|
|
|
9
|
-
**Requirements:** macOS with [Things 3](https://culturedcode.com/things/) installed
|
|
9
|
+
**Requirements:** macOS with [Things 3](https://culturedcode.com/things/) installed and Python 3.12+.
|
|
10
10
|
|
|
11
|
-
### 1.
|
|
11
|
+
### 1. Install
|
|
12
|
+
|
|
13
|
+
Run directly with [`uvx`](https://docs.astral.sh/uv/) (no install needed):
|
|
12
14
|
|
|
13
15
|
```sh
|
|
14
|
-
|
|
15
|
-
cd things-api
|
|
16
|
-
uv venv
|
|
17
|
-
uv pip install -e .
|
|
16
|
+
uvx things-api
|
|
18
17
|
```
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
Or install with pip:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
pip install things-api
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Or clone the repo for development:
|
|
21
26
|
|
|
22
27
|
```sh
|
|
23
|
-
|
|
28
|
+
git clone https://github.com/jaydenk/things-api.git
|
|
29
|
+
cd things-api
|
|
30
|
+
uv venv && uv pip install -e .
|
|
24
31
|
```
|
|
25
32
|
|
|
26
|
-
|
|
33
|
+
### 2. Configure
|
|
34
|
+
|
|
35
|
+
Create a `.env` file in the directory you'll run the server from:
|
|
27
36
|
|
|
28
37
|
```dotenv
|
|
29
38
|
THINGS_API_TOKEN=choose-a-secure-random-string
|
|
@@ -42,7 +51,7 @@ See [docs/configuration.md](docs/configuration.md) for all configuration options
|
|
|
42
51
|
### 3. Run
|
|
43
52
|
|
|
44
53
|
```sh
|
|
45
|
-
|
|
54
|
+
things-api
|
|
46
55
|
```
|
|
47
56
|
|
|
48
57
|
The server starts on `http://localhost:5225`.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Things API launchd agent
|
|
3
3
|
|
|
4
4
|
Install:
|
|
5
|
-
1. Edit this file — set WorkingDirectory and
|
|
5
|
+
1. Edit this file — set WorkingDirectory and the path to uvx/uv
|
|
6
6
|
2. Ensure your .env file exists in the working directory with THINGS_API_TOKEN set
|
|
7
7
|
3. cp com.things-api.server.plist ~/Library/LaunchAgents/
|
|
8
8
|
4. launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.things-api.server.plist
|
|
@@ -18,30 +18,29 @@
|
|
|
18
18
|
<key>Label</key>
|
|
19
19
|
<string>com.things-api.server</string>
|
|
20
20
|
|
|
21
|
-
<!--
|
|
21
|
+
<!-- The directory containing your .env file -->
|
|
22
22
|
<key>WorkingDirectory</key>
|
|
23
|
-
<string>/path/to/
|
|
23
|
+
<string>/path/to/directory-with-env-file</string>
|
|
24
24
|
|
|
25
25
|
<!--
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
Replace /path/to/uv with the output of: which uv
|
|
26
|
+
Run from PyPI via uvx (recommended).
|
|
27
|
+
Replace /path/to/uvx with the output of: which uvx
|
|
29
28
|
-->
|
|
30
29
|
<key>ProgramArguments</key>
|
|
31
30
|
<array>
|
|
32
|
-
<string>/path/to/
|
|
33
|
-
<string>run</string>
|
|
31
|
+
<string>/path/to/uvx</string>
|
|
34
32
|
<string>things-api</string>
|
|
35
33
|
</array>
|
|
36
34
|
|
|
37
35
|
<!--
|
|
38
|
-
|
|
39
|
-
Uncomment this block and comment out
|
|
40
|
-
Replace /path/to/
|
|
36
|
+
Alternative: run from a cloned repo with uv.
|
|
37
|
+
Uncomment this block and comment out the uvx block above.
|
|
38
|
+
Replace /path/to/uv with the output of: which uv
|
|
41
39
|
|
|
42
40
|
<key>ProgramArguments</key>
|
|
43
41
|
<array>
|
|
44
|
-
<string>/path/to/
|
|
42
|
+
<string>/path/to/uv</string>
|
|
43
|
+
<string>run</string>
|
|
45
44
|
<string>things-api</string>
|
|
46
45
|
</array>
|
|
47
46
|
-->
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Deployment
|
|
2
2
|
|
|
3
|
-
These instructions assume you've already completed the [Getting Started](../README.md#getting-started) steps
|
|
3
|
+
These instructions assume you've already completed the [Getting Started](../README.md#getting-started) steps and have a `.env` file configured.
|
|
4
4
|
|
|
5
5
|
## Running as a launchd service
|
|
6
6
|
|
|
@@ -8,16 +8,28 @@ A launchd agent keeps Things API running in the background. It starts automatica
|
|
|
8
8
|
|
|
9
9
|
### 1. Edit the plist template
|
|
10
10
|
|
|
11
|
-
Open `com.things-api.server.plist`
|
|
11
|
+
Open `com.things-api.server.plist` and set two paths:
|
|
12
12
|
|
|
13
|
-
**`WorkingDirectory`** — the absolute path to your cloned `things-api` directory.
|
|
13
|
+
**`WorkingDirectory`** — the absolute path to the directory containing your `.env` file. If you cloned the repo, this is your `things-api` directory. If you installed via pip/uvx, this is wherever you put your `.env`.
|
|
14
14
|
|
|
15
15
|
```xml
|
|
16
16
|
<key>WorkingDirectory</key>
|
|
17
17
|
<string>/Users/yourname/things-api</string>
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
**`ProgramArguments`** — the
|
|
20
|
+
**`ProgramArguments`** — how to launch the server. Use full paths — launchd does not inherit your shell's `PATH`.
|
|
21
|
+
|
|
22
|
+
If installed via **pip** or **uvx**:
|
|
23
|
+
|
|
24
|
+
```xml
|
|
25
|
+
<key>ProgramArguments</key>
|
|
26
|
+
<array>
|
|
27
|
+
<string>/opt/homebrew/bin/uvx</string>
|
|
28
|
+
<string>things-api</string>
|
|
29
|
+
</array>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
If running from a **cloned repo**:
|
|
21
33
|
|
|
22
34
|
```xml
|
|
23
35
|
<key>ProgramArguments</key>
|
|
@@ -28,7 +40,7 @@ Open `com.things-api.server.plist` in the project root and set two paths:
|
|
|
28
40
|
</array>
|
|
29
41
|
```
|
|
30
42
|
|
|
31
|
-
|
|
43
|
+
Find the correct path with `which uvx` or `which uv`.
|
|
32
44
|
|
|
33
45
|
### 2. Install and load
|
|
34
46
|
|
|
@@ -89,7 +89,19 @@ def main() -> None:
|
|
|
89
89
|
level=logging.INFO,
|
|
90
90
|
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
|
|
91
91
|
)
|
|
92
|
-
|
|
92
|
+
try:
|
|
93
|
+
settings = Settings()
|
|
94
|
+
except Exception:
|
|
95
|
+
print(
|
|
96
|
+
"Error: THINGS_API_TOKEN is not set.\n"
|
|
97
|
+
"\n"
|
|
98
|
+
"Set it as an environment variable:\n"
|
|
99
|
+
" THINGS_API_TOKEN=your-secret-token things-api\n"
|
|
100
|
+
"\n"
|
|
101
|
+
"Or create a .env file in the current directory:\n"
|
|
102
|
+
" echo 'THINGS_API_TOKEN=your-secret-token' > .env"
|
|
103
|
+
)
|
|
104
|
+
raise SystemExit(1)
|
|
93
105
|
app = create_app(settings)
|
|
94
106
|
uvicorn.run(
|
|
95
107
|
app,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|