Skip to content

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

Open
Petru101 wants to merge 1 commit into
EbbLabs:mainfrom
Petru101:fix/oauth-expiry-string
Open

Petru101 wants to merge 1 commit into
EbbLabs:mainfrom
Petru101:fix/oauth-expiry-string

Conversation

@Petru101

Copy link
Copy Markdown

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

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 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)

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