This repository has been archived by the owner on Nov 5, 2019. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add two new storage classes for #319.
* LockedStorage - implements a generic storage base class that uses a `threading.Lock` like-object. * DictionaryStorage - implements an optionally-locked storage over a dictionary-like object. Additionally: * Updated `file.Storage` to use `LockedStorage`. * Remove `flask_util.FlaskSessionStorage` and replaced it with `DictionaryStorage`.
- Loading branch information
Jon Wayne Parrott
committed
Nov 30, 2015
1 parent
4cf98dc
commit d230fd2
Showing
9 changed files
with
318 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
oauth2client.dictionary_storage module | ||
====================================== | ||
|
||
.. automodule:: oauth2client.dictionary_storage | ||
:members: | ||
:undoc-members: | ||
:show-inheritance: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
oauth2client.locked_storage module | ||
================================== | ||
|
||
.. automodule:: oauth2client.locked_storage | ||
:members: | ||
:undoc-members: | ||
:show-inheritance: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# Copyright 2014 Google Inc. All rights reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
"""Dictionary storage for OAuth2 Credentials.""" | ||
|
||
from oauth2client.client import OAuth2Credentials | ||
from oauth2client.locked_storage import LockedStorage | ||
|
||
|
||
class DictionaryStorage(LockedStorage): | ||
"""Store and retrieve credentials to and from a dictionary-like object.""" | ||
|
||
def __init__(self, dictionary, key, lock=None): | ||
"""Construct a DictionaryStorage instance. | ||
Args: | ||
dictionary: A dictionary or dictionary-like object. | ||
key: A hashable or a function returning a hashable. The credentials | ||
will be stored in ``dictionary[key]``. | ||
lock: An optional threading.Lock-like object. The lock will be | ||
acquired before anything is written or read from the | ||
dictionary. | ||
""" | ||
super(DictionaryStorage, self).__init__(lock=lock) | ||
self._dictionary = dictionary | ||
self._key = key | ||
|
||
def _get_key(self): | ||
"""Return the key for storing the credentials. | ||
If self._key is a callable, it will return the result of calling | ||
self._key. | ||
""" | ||
if callable(self._key): | ||
return self._key() | ||
else: | ||
return self._key | ||
|
||
def locked_get(self): | ||
"""Retrieve the credentials from the dictionary, if they exist.""" | ||
key = self._get_key() | ||
serialized = self._dictionary.get(key) | ||
|
||
if serialized is None: | ||
return None | ||
|
||
credentials = OAuth2Credentials.from_json(serialized) | ||
credentials.set_store(self) | ||
|
||
return credentials | ||
|
||
def locked_put(self, credentials): | ||
"""Save the credentials to the dictionary.""" | ||
key = self._get_key() | ||
serialized = credentials.to_json() | ||
self._dictionary[key] = serialized | ||
|
||
def locked_delete(self): | ||
"""Remove the credentials from the dictionary, if they exist.""" | ||
key = self._get_key() | ||
self._dictionary.pop(key, None) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Copyright 2014 Google Inc. All rights reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
"""Lock-safe storage for OAuth2 Credentials. | ||
This module provides the LockStorage base class that is used to provide | ||
optional lock safety to Storage sub-classes. | ||
""" | ||
|
||
import os | ||
import threading | ||
|
||
from oauth2client.client import Storage as Storage | ||
|
||
|
||
__author__ = 'jonwayne@google.com (Jon Wayne Parrott)' | ||
|
||
|
||
class LockedStorage(Storage): | ||
"""Storage base class that provides optional locking.""" | ||
|
||
def __init__(self, lock=None): | ||
"""Create a LockedStorage instance. | ||
Args: | ||
lock: An optional threading.Lock-like object. Must implement at | ||
least acquire() and release(). Does not need to be re-entrant. | ||
""" | ||
self._lock = lock | ||
|
||
def acquire_lock(self): | ||
"""Acquires any lock necessary to access this storage.""" | ||
if self._lock is not None: | ||
self._lock.acquire() | ||
|
||
def release_lock(self): | ||
"""Releases the storage lock. | ||
Trying to release a lock that isn't held will result in a | ||
RuntimeError. | ||
""" | ||
if self._lock is not None: | ||
self._lock.release() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# Copyright 2014 Google Inc. All rights reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
"""Unit tests for oauth2client.dictionary_storage""" | ||
|
||
import unittest | ||
|
||
from oauth2client import GOOGLE_TOKEN_URI | ||
from oauth2client.client import OAuth2Credentials | ||
from oauth2client.dictionary_storage import DictionaryStorage | ||
|
||
|
||
__author__ = 'jonwayne@google.com (Jon Wayne Parrott)' | ||
|
||
|
||
class DictionaryStorageTests(unittest.TestCase): | ||
|
||
def _generate_credentials(self, scopes=None): | ||
return OAuth2Credentials( | ||
'access_tokenz', | ||
'client_idz', | ||
'client_secretz', | ||
'refresh_tokenz', | ||
'3600', | ||
GOOGLE_TOKEN_URI, | ||
'Test', | ||
id_token={ | ||
'sub': '123', | ||
'email': 'user@example.com' | ||
}, | ||
scopes=scopes) | ||
|
||
def test_string_key(self): | ||
dictionary = {} | ||
key = 'credentials' | ||
credentials = self._generate_credentials() | ||
storage = DictionaryStorage(dictionary, key) | ||
|
||
storage.put(credentials) | ||
|
||
self.assertTrue(key in dictionary) | ||
|
||
retrieved = storage.get() | ||
|
||
self.assertEqual(retrieved.access_token, credentials.access_token) | ||
|
||
storage.delete() | ||
|
||
self.assertTrue(key not in dictionary) | ||
self.assertTrue(storage.get() is None) | ||
|
||
def test_function_key(self): | ||
dictionary = {} | ||
key = 'credentials' | ||
credentials = self._generate_credentials() | ||
storage = DictionaryStorage(dictionary, lambda: key) | ||
|
||
storage.put(credentials) | ||
|
||
self.assertTrue(key in dictionary) | ||
|
||
retrieved = storage.get() | ||
|
||
self.assertEqual(retrieved.access_token, credentials.access_token) | ||
|
||
storage.delete() | ||
|
||
self.assertTrue(key not in dictionary) | ||
self.assertTrue(storage.get() is None) | ||
|
||
|
||
if __name__ == '__main__': # pragma: NO COVER | ||
unittest.main() |
Oops, something went wrong.