Skip to content

Accept an ISO 8601 string as expiry_time in load_oauth_session - #416

Merged
tehkillerbee merged 3 commits into
EbbLabs:mainfrom
Petru101:fix/oauth-expiry-string
Nov 5, 2026
Merged

tehkillerbee merged 3 commits into
EbbLabs:mainfrom
Petru101:fix/oauth-expiry-string

Conversation

@Petru101

Copy link
Copy Markdown
Contributor

Since the 0.9.0 changes, every request checks the access token's expiry time before it's sent (Requests._access_token_expired). Applications that pass expiry_time to load_oauth_session as a string, as they could until now because tidalapi never used it, now get AttributeError: 'str' object has no attribute 'tzinfo' on every request, including the sessions request inside load_oauth_session itself.

High Tide is one of them: it stores str(session.expiry_time) in the keyring and passes that back on the next start, so it would stop working with 0.9.0.

load_oauth_session now parses a string with datetime.fromisoformat, as load_session_from_file already does, and ignores it with a log message if it can't be parsed (e.g. "None"). The new offline tests in test_token_refresh.py cover str(datetime), an isoformat() string and an invalid string, and fail with that AttributeError without the change.

🤖 Generated with Claude Code

@tehkillerbee

tehkillerbee commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

Welcome and thanks for your contribution.

FYI I had a separate commit here that removes datetime.utcnow() usage (will be merged ASAP)
bee481b

This essentially means that we use timezone aware datetime, str() would return something like
2026-10-15 12:53:00.123456+00:00

So whether this works depends on how this string was generated. If it was generated using utcnow(), it should be treated as UTC. It will then look something like:
2026-10-15 12:53:00.123456

Something like this:

if isinstance(expiry_time, str):
    # Applications often store the expiry time as text
    try:
        expiry_time = datetime.datetime.fromisoformat(expiry_time)
    except ValueError:
        log.info("Ignoring invalid expiry_time %r", expiry_time)
        expiry_time = None

if expiry_time is not None and expiry_time.tzinfo is None:
    # Treat naive datetimes (e.g. from legacy utcnow()) as UTC
    expiry_time = expiry_time.replace(tzinfo=datetime.timezone.utc)

Petru101 and others added 2 commits November 5, 2026 21:50
Applications such as High Tide store the token's expiry time as text and pass it to load_oauth_session. tidalapi didn't use the value before, but now that requests refresh the access token shortly before it expires, a string made every request fail with AttributeError: 'str' object has no attribute 'tzinfo'. It is now parsed with datetime.fromisoformat, as load_session_from_file does, and ignored if it can't be parsed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tehkillerbee
tehkillerbee force-pushed the fix/oauth-expiry-string branch from 37ddf65 to e8df902 Compare November 5, 2026 20:54
@tehkillerbee
tehkillerbee merged commit c620bb1 into EbbLabs:main Nov 5, 2026
6 checks passed
@Petru101

Petru101 commented Nov 5, 2026

Copy link
Copy Markdown
Contributor Author

Thanks, sorry I missed your suggestion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants