Skip to content

Commit f99159a

Browse files
matinclaude
andauthored
Deprecate Garth — final release v0.8.0 (#223)
* Deprecate Garth — final release v0.8.0 Garmin changed their auth flow, breaking the mobile auth approach Garth depends on. This is the final release with: - DeprecationWarning on import pointing to the announcement - Telemetry disabled by default - Development Status classifier set to Inactive - README and docs updated with deprecation notices See #222 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Move deprecation warning after imports to avoid noqa comments Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix ty type checker error for logfire = None assignment Newer ty versions promote invalid-assignment to error for assigning None to a module type. Add knot: ignore comment to suppress. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix ty: ignore syntax and upgrade ty to 0.0.26 Use correct `ty: ignore[invalid-assignment]` comment syntax and upgrade ty in lockfile to match CI. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Update telemetry docs and docstring to reflect disabled defaults Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 6c1b537 commit f99159a

10 files changed

Lines changed: 90 additions & 197 deletions

File tree

README.md

Lines changed: 20 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,34 @@
11
# Garth
22

3-
[![CI](https://github.com/matin/garth/actions/workflows/ci.yml/badge.svg?branch=main&event=push)](https://github.com/matin/garth/actions/workflows/ci.yml?query=event%3Apush+branch%3Amain+workflow%3ACI)
4-
[![codecov](https://codecov.io/gh/matin/garth/branch/main/graph/badge.svg?token=0EFFYJNFIL)](https://codecov.io/gh/matin/garth)
3+
> **Garth is deprecated and no longer maintained.** Garmin changed their auth
4+
> flow, breaking the mobile auth approach that Garth depends on. I'm not in a
5+
> position to dedicate the time to adapt to these changes. See the
6+
> [announcement](https://github.com/matin/garth/discussions/222) for details.
7+
> Anyone is welcome to fork Garth as a starting point for a new library.
8+
59
[![PyPI version](https://img.shields.io/pypi/v/garth.svg?logo=python&logoColor=brightgreen&color=brightgreen)](https://pypi.org/project/garth/)
610
[![PyPI - Downloads](https://img.shields.io/pypi/dm/garth)](https://pypistats.org/packages/garth)
7-
[![Documentation](https://img.shields.io/badge/docs-readthedocs-blue)](https://garth.readthedocs.io)
811

912
Garmin SSO auth + Connect Python client
1013

11-
## Features
12-
13-
- OAuth1/OAuth2 authentication (OAuth1 token lasts ~1 year)
14-
- MFA support with custom handlers
15-
- Auto-refresh of OAuth2 token
16-
- Auto-resume from `GARTH_HOME` or `GARTH_TOKEN` environment variables
17-
- Works on Google Colab
18-
- Pydantic dataclasses for validated data
19-
- Built-in telemetry for diagnosing auth issues
20-
- Full test coverage
21-
22-
## Installation
23-
24-
```bash
25-
pip install garth
26-
```
27-
28-
## Quick Start
29-
30-
### Authenticate and save session
31-
32-
```python
33-
import garth
34-
from getpass import getpass
35-
36-
garth.login(input("Email: "), getpass("Password: "))
37-
garth.save("~/.garth")
38-
```
39-
40-
### Resume session
41-
42-
```python
43-
import garth
44-
from garth.exc import GarthException
14+
## About
4515

46-
garth.resume("~/.garth")
47-
try:
48-
garth.client.username
49-
except GarthException:
50-
# Session is expired. You'll need to log in again
51-
pass
52-
```
16+
Garth was a Python library for Garmin Connect API access with OAuth
17+
authentication. It reached 350k+ downloads per month and was translated into
18+
multiple programming languages.
5319

54-
Or use environment variables for automatic session restoration:
20+
Garmin recently changed their auth flow, breaking the mobile auth approach
21+
that Garth and other libraries depend on
22+
([#217](https://github.com/matin/garth/issues/217)). This is the final
23+
release.
5524

56-
```bash
57-
export GARTH_HOME=~/.garth
58-
# or
59-
export GARTH_TOKEN="eyJvYXV0aF90b2tlbi..." # from `uvx garth login`
60-
```
25+
## For existing users
6126

62-
```python
63-
import garth
64-
# Session is automatically loaded
65-
garth.client.username
66-
```
67-
68-
### Fetch data
69-
70-
```python
71-
# Get daily stress
72-
garth.DailyStress.list("2023-07-23", 7)
73-
74-
# Get sleep data
75-
garth.SleepData.get("2023-07-20")
76-
77-
# Get weight
78-
garth.WeightData.list("2025-06-01", 30)
79-
80-
# Direct API calls
81-
garth.connectapi("/usersummary-service/stats/stress/weekly/2023-07-05/52")
82-
```
27+
If you already have a saved session with a valid OAuth1 token, Garth may
28+
continue to work until that token expires (~1 year from when it was issued).
29+
New logins will not work.
8330

8431
## Documentation
8532

86-
Full documentation at **[garth.readthedocs.io](https://garth.readthedocs.io)**
87-
88-
## MCP Server
89-
90-
[`garth-mcp-server`](https://github.com/matin/garth-mcp-server) is in early development.
91-
92-
To generate your `GARTH_TOKEN`, use `uvx garth login`.
93-
94-
## Star History
95-
96-
<!-- markdownlint-disable MD013 -->
97-
<a href="https://www.star-history.com/#matin/garth&Date">
98-
<picture>
99-
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=matin/garth&type=Date&theme=dark" />
100-
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=matin/garth&type=Date" />
101-
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=matin/garth&type=Date" />
102-
</picture>
103-
</a>
104-
<!-- markdownlint-enable MD013 -->
33+
Documentation is still available at
34+
**[garth.readthedocs.io](https://garth.readthedocs.io)** for reference.

docs/getting-started.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Getting Started
22

3+
!!! warning "Deprecated"
4+
**Garth is deprecated and no longer maintained.** New logins will not work
5+
due to changes in Garmin's auth flow. See the
6+
[announcement](https://github.com/matin/garth/discussions/222) for details.
7+
38
## Installation
49

510
### From PyPI

docs/index.md

Lines changed: 21 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,65 +2,34 @@
22

33
Garmin SSO auth + Connect Python client
44

5-
[![CI](https://github.com/matin/garth/actions/workflows/ci.yml/badge.svg?branch=main&event=push)](https://github.com/matin/garth/actions/workflows/ci.yml?query=event%3Apush+branch%3Amain+workflow%3ACI)
6-
[![codecov](https://codecov.io/gh/matin/garth/branch/main/graph/badge.svg?token=0EFFYJNFIL)](https://codecov.io/gh/matin/garth)
7-
[![PyPI version](https://img.shields.io/pypi/v/garth.svg?logo=python&logoColor=brightgreen&color=brightgreen)](https://pypi.org/project/garth/)
8-
[![PyPI - Downloads](https://img.shields.io/pypi/dm/garth)](https://pypistats.org/packages/garth)
5+
!!! warning "Deprecated"
6+
**Garth is deprecated and no longer maintained.** Garmin changed their auth
7+
flow, breaking the mobile auth approach that Garth depends on. See the
8+
[announcement](https://github.com/matin/garth/discussions/222) for details.
9+
Anyone is welcome to fork Garth as a starting point for a new library.
910

10-
## Why Garth?
11+
## About
1112

12-
Garth is meant for personal use and follows the philosophy that your data is
13-
your data. You should be able to download it and analyze it in the way that
14-
you'd like. In my case, that means processing with Google Colab, Pandas,
15-
Matplotlib, etc.
13+
Garth was a Python library for Garmin Connect API access with OAuth
14+
authentication. It reached 350k+ downloads per month and was translated into
15+
multiple programming languages.
1616

17-
There are already a few Garmin Connect libraries. Why write another?
17+
Garmin recently changed their auth flow, breaking the mobile auth approach
18+
that Garth and other libraries depend on
19+
([#217](https://github.com/matin/garth/issues/217)). This is the final
20+
release.
1821

19-
### Authentication and stability
22+
## For existing users
2023

21-
The most important reasoning is to build a library with authentication that
22-
works on [Google Colab](https://colab.research.google.com/) and doesn't require
23-
tools like Cloudscraper. Garth, in comparison:
24+
If you already have a saved session with a valid OAuth1 token, Garth may
25+
continue to work until that token expires (~1 year from when it was issued).
26+
New logins will not work.
2427

25-
1. Uses OAuth1 and OAuth2 token authentication after initial login
26-
1. OAuth1 token survives for a year
27-
1. Supports MFA
28-
1. Auto-refresh of OAuth2 token when expired
29-
1. Works on Google Colab
30-
1. Uses Pydantic dataclasses to validate and simplify use of data
31-
1. Full test coverage
28+
## Documentation
3229

33-
### JSON vs HTML
30+
The rest of this documentation is preserved for reference.
3431

35-
Using `garth.connectapi()` allows you to make requests to the Connect API
36-
and receive JSON vs needing to parse HTML. You can use the same endpoints the
37-
mobile app uses.
38-
39-
This also goes back to authentication. Garth manages the necessary Bearer
40-
Authentication (along with auto-refresh) necessary to make requests routed to
41-
the Connect API.
42-
43-
## Quick Start
44-
45-
```bash
46-
pip install garth
47-
```
48-
49-
```python
50-
import garth
51-
from getpass import getpass
52-
53-
# Login and save session
54-
garth.login(input("Email: "), getpass("Password: "))
55-
garth.save("~/.garth")
56-
57-
# Later, resume the session
58-
garth.resume("~/.garth")
59-
```
60-
61-
## Next Steps
62-
63-
- [Getting Started](getting-started.md) - Detailed authentication and session management
32+
- [Getting Started](getting-started.md) - Authentication and session management
6433
- [Configuration](configuration.md) - Domain and proxy settings
65-
- [API Reference](api/stats.md) - Explore available data types
34+
- [API Reference](api/stats.md) - Available data types
6635
- [Examples](examples.md) - Google Colab notebooks

docs/telemetry.md

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,8 @@
22

33
Garth includes built-in telemetry using
44
[Pydantic Logfire](https://pydantic.dev/logfire) for logging and observability.
5-
Telemetry is **enabled by default** to help diagnose authentication issues. It
6-
is **isolated to Garth's requests only** — it won't affect other HTTP clients
7-
in your application.
8-
9-
## Why telemetry is on by default
10-
11-
Garmin occasionally changes their authentication endpoints in ways that only
12-
affect a subset of users — for example, the
13-
[SSO migration](https://github.com/cyberjunky/python-garminconnect/issues/332)
14-
that caused 403 errors for some users while others were unaffected. Without
15-
telemetry, these issues are nearly impossible to reproduce or diagnose. With
16-
default-on telemetry, maintainers can look up the exact request/response
17-
sequence for a failing session using the session ID.
18-
19-
Each session generates a unique `session_id` that is printed to stdout when
20-
garth is imported:
21-
22-
```text
23-
Garth session: a01e3fc1d5ac4c9a
24-
```
25-
26-
When reporting issues, include your session ID so maintainers can look up your
27-
request logs.
5+
Telemetry is **disabled by default** as of v0.8.0 since Garth is no longer
6+
actively maintained.
287

298
## Disable telemetry
309

@@ -66,8 +45,8 @@ Telemetry settings can be configured via environment variables with the
6645

6746
| Environment Variable | Default | Description |
6847
|---|---|---|
69-
| `GARTH_TELEMETRY_ENABLED` | `true` | Enable/disable telemetry |
70-
| `GARTH_TELEMETRY_SEND_TO_LOGFIRE` | `true` | Send to Logfire Cloud |
48+
| `GARTH_TELEMETRY_ENABLED` | `false` | Enable/disable telemetry |
49+
| `GARTH_TELEMETRY_SEND_TO_LOGFIRE` | `false` | Send to Logfire Cloud |
7150
| `GARTH_TELEMETRY_TOKEN` | *(built-in)* | Logfire write token |
7251

7352
## What gets logged

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ requires-python = ">=3.10"
1616
readme = "README.md"
1717
license = {text = "MIT"}
1818
classifiers = [
19-
"Development Status :: 5 - Production/Stable",
19+
"Development Status :: 7 - Inactive",
2020
"License :: OSI Approved :: MIT License",
2121
"Programming Language :: Python :: 3.10",
2222
"Programming Language :: Python :: 3.11",

src/garth/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import warnings
2+
13
from .data import (
24
Activity,
35
BodyBatteryData,
@@ -32,6 +34,14 @@
3234
from .version import __version__
3335

3436

37+
warnings.warn(
38+
"Garth is deprecated and no longer maintained. "
39+
"See https://github.com/matin/garth/discussions/222",
40+
DeprecationWarning,
41+
stacklevel=2,
42+
)
43+
44+
3545
__all__ = [
3646
"Activity",
3747
"BodyBatteryData",

src/garth/telemetry.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
LOGFIRE_AVAILABLE = True
1818
except ImportError: # pragma: no cover
19-
logfire = None # type: ignore[assignment]
19+
logfire = None # type: ignore[assignment] # ty: ignore[invalid-assignment]
2020
LOGFIRE_AVAILABLE = False
2121

2222

@@ -109,8 +109,8 @@ class Telemetry(BaseSettings):
109109
extra="ignore",
110110
)
111111

112-
enabled: bool = True
113-
send_to_logfire: bool = True
112+
enabled: bool = False
113+
send_to_logfire: bool = False
114114
token: str = DEFAULT_TOKEN
115115
callback: Callable[[dict], None] | None = Field(default=None, exclude=True)
116116
session_id: str = Field(
@@ -176,11 +176,11 @@ def configure(
176176
callback: Callable[[dict], None] | None = None,
177177
):
178178
"""
179-
Configure telemetry. Enabled by default.
179+
Configure telemetry. Disabled by default.
180180
181181
Args:
182-
enabled: Enable/disable telemetry (default: True)
183-
send_to_logfire: Send to Logfire Cloud (default: True)
182+
enabled: Enable/disable telemetry (default: False)
183+
send_to_logfire: Send to Logfire Cloud (default: False)
184184
token: Logfire write token
185185
callback: Custom callback for telemetry data. If provided,
186186
logfire will not be configured and data will be passed

src/garth/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.7.11"
1+
__version__ = "0.8.0"

tests/test_telemetry.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ def test_telemetry_defaults(monkeypatch):
5252
monkeypatch.delenv("GARTH_TELEMETRY_SEND_TO_LOGFIRE", raising=False)
5353

5454
t = Telemetry()
55-
assert t.enabled is True
56-
assert t.send_to_logfire is True
55+
assert t.enabled is False
56+
assert t.send_to_logfire is False
5757
assert t.token == DEFAULT_TOKEN
5858
assert t.callback is None
5959
assert t.session_id # non-empty

0 commit comments

Comments
 (0)