Skip to content

Commit ed400f9

Browse files
Fix: Convert scopes set to list in Credentials.__init__
This change ensures that if a set of scopes is passed to Credentials, it is converted to a list. This prevents issues with JSON serialization (to_json failure) and ensures consistent mutability behavior for the scopes property. Fixes #1145
1 parent 0e28e6f commit ed400f9

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

google/oauth2/credentials.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,10 @@ def __init__(
141141
self.expiry = expiry
142142
self._refresh_token = refresh_token
143143
self._id_token = id_token
144-
self._scopes = scopes
144+
if scopes is not None and isinstance(scopes, set):
145+
self._scopes = list(scopes)
146+
else:
147+
self._scopes = scopes
145148
self._default_scopes = default_scopes
146149
self._granted_scopes = granted_scopes
147150
self._token_uri = token_uri
@@ -207,7 +210,7 @@ def refresh_token(self):
207210

208211
@property
209212
def scopes(self):
210-
"""Optional[str]: The OAuth 2.0 permission scopes."""
213+
"""Optional[Sequence[str]]: The OAuth 2.0 permission scopes."""
211214
return self._scopes
212215

213216
@property

tests/oauth2/test_credentials.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,31 @@ def make_credentials(cls):
5555
enable_reauth_refresh=True,
5656
)
5757

58+
def test_init_with_set_scopes(self):
59+
# Regression test for https://github.com/googleapis/google-auth-library-python/issues/1145
60+
scopes_set = {"a", "b"}
61+
creds = credentials.Credentials(token="token", scopes=scopes_set)
62+
63+
# Verify scopes are converted to a list
64+
assert isinstance(creds.scopes, list)
65+
assert set(creds.scopes) == scopes_set
66+
67+
# Verify internal storage is a list (ensure consistent mutability)
68+
assert isinstance(creds._scopes, list)
69+
70+
# Verify consistency (property returns the same object)
71+
assert creds.scopes is creds.scopes
72+
73+
# Verify modifications persist
74+
creds.scopes.append("c")
75+
assert "c" in creds.scopes
76+
assert len(creds.scopes) == 3
77+
78+
# Verify to_json works
79+
json_output = creds.to_json()
80+
data = json.loads(json_output)
81+
assert set(data["scopes"]) == {"a", "b", "c"}
82+
5883
def test_default_state(self):
5984
credentials = self.make_credentials()
6085
assert not credentials.valid

0 commit comments

Comments
 (0)